diff --git a/src/main/java/com/alterdekim/game/component/processors/FriendProcessor.java b/src/main/java/com/alterdekim/game/component/processors/FriendProcessor.java index 391dac6..93fd300 100644 --- a/src/main/java/com/alterdekim/game/component/processors/FriendProcessor.java +++ b/src/main/java/com/alterdekim/game/component/processors/FriendProcessor.java @@ -7,11 +7,7 @@ import com.alterdekim.game.component.result.LongPollResultType; import com.alterdekim.game.dto.FriendResult; import com.alterdekim.game.dto.FriendState; import com.alterdekim.game.dto.UserResult; -import com.alterdekim.game.service.FriendServiceImpl; -import com.alterdekim.game.service.UserServiceImpl; import com.alterdekim.game.util.ListUtil; -import lombok.Setter; -import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; import java.util.Comparator; @@ -32,7 +28,7 @@ public class FriendProcessor extends Processor { return new LongPollResultSingle<>(getType(), friends2Users(getParent().getFriendService().getFriendsOfUserId(userId)) .stream() - .map(f -> new FriendResult(FriendState.ADD, f.getId(), f.getUsername())) + .map(f -> new FriendResult(FriendState.ADD, f.getId(), f.getUsername(), f.getAvatarId())) .collect(Collectors.toList())); } @@ -45,16 +41,16 @@ public class FriendProcessor extends Processor { List fr = new ArrayList<>(); for( UserResult r : clientFriends ) { if( userResults.stream().noneMatch(t -> t.getId().longValue() == r.getId().longValue()) ) { - fr.add(new FriendResult(FriendState.REMOVE, r.getId(), r.getUsername())); + fr.add(new FriendResult(FriendState.REMOVE, r.getId(), r.getUsername(), r.getAvatarId())); continue; } UserResult r1 = userResults.stream().filter( t -> t.getId().longValue() == r.getId().longValue()).findFirst().get(); if( !r.equals(r1) ) { - fr.add(new FriendResult(FriendState.ADD, r1.getId(), r1.getUsername())); + fr.add(new FriendResult(FriendState.ADD, r1.getId(), r1.getUsername(), r1.getAvatarId())); } urr.remove(r1); } - urr.forEach(r -> fr.add(new FriendResult(FriendState.ADD, r.getId(), r.getUsername()))); + urr.forEach(r -> fr.add(new FriendResult(FriendState.ADD, r.getId(), r.getUsername(), r.getAvatarId()))); return fr.stream().sorted(Comparator.comparingLong(FriendResult::getId)).collect(Collectors.toList()); } diff --git a/src/main/java/com/alterdekim/game/controller/StaticController.java b/src/main/java/com/alterdekim/game/controller/StaticController.java index cf1266b..2634c2d 100644 --- a/src/main/java/com/alterdekim/game/controller/StaticController.java +++ b/src/main/java/com/alterdekim/game/controller/StaticController.java @@ -6,6 +6,7 @@ import com.alterdekim.game.entities.Image; import com.alterdekim.game.entities.User; import com.alterdekim.game.repository.ImageRepository; import com.alterdekim.game.service.FriendServiceImpl; +import com.alterdekim.game.service.GamesService; import com.alterdekim.game.service.UserServiceImpl; import com.alterdekim.game.util.AuthenticationUtil; import com.alterdekim.game.util.Hash; @@ -38,6 +39,9 @@ public class StaticController { @Autowired private ImageRepository imageRepository; + @Autowired + private GamesService gamesService; + @GetMapping("/rules") public String rulesPage(Model model) { AuthenticationUtil.authProfile(model, userService); @@ -70,6 +74,15 @@ public class StaticController { return "friends"; } + @GetMapping("/followers") + public String followersPage(Model model) { + Long userId = AuthenticationUtil.authProfile(model, userService).getId(); + model.addAttribute("friends", friendService.getFollowersOfUserId(userId).stream() + .map(l -> userService.findById(l)) + .map(u -> new FriendPageResult("/profile/"+u.getId(), "background-image: url(\"/image/store/"+u.getAvatarId()+"\");", u.getUsername(), u.getId(), u.getDisplayName()))); + return "followers"; + } + @GetMapping("/profile/{id}") public String profilePage(@PathVariable("id") Long id, Model model) { User self = AuthenticationUtil.authProfile(model, userService); @@ -79,8 +92,8 @@ public class StaticController { u.getUsername(), u.getId(), u.getDisplayName(), - 0, - 0, + gamesService.getGamesCount(u.getId()), + gamesService.getWonGamesCount(u.getId()), friendService.getFriendsOfUserId(u.getId()).size(), friendService.getFriendState(self.getId(), u.getId()))); return "profile"; @@ -95,12 +108,7 @@ public class StaticController { options.add(new SelectOption("they/them", false)); options.add(new SelectOption("idc", false)); String p = u.getPronouns(); - options = options.stream().map(o -> { - if(p.equals(o.getText())) { - return new SelectOption(o.getText(), true); - } - return new SelectOption(o.getText(), false); - }).collect(Collectors.toList()); + options = options.stream().map(o -> new SelectOption(o.getText(), p.equals(o.getText()))).collect(Collectors.toList()); model.addAttribute("options", options); return "settings"; } diff --git a/src/main/java/com/alterdekim/game/dto/FriendResult.java b/src/main/java/com/alterdekim/game/dto/FriendResult.java index b8cfaca..8d202d9 100644 --- a/src/main/java/com/alterdekim/game/dto/FriendResult.java +++ b/src/main/java/com/alterdekim/game/dto/FriendResult.java @@ -11,4 +11,5 @@ public class FriendResult { private FriendState action; private Long id; private String username; + private Long avatarId; } diff --git a/src/main/java/com/alterdekim/game/dto/ProfilePageResult.java b/src/main/java/com/alterdekim/game/dto/ProfilePageResult.java index 19ebbf8..30bc939 100644 --- a/src/main/java/com/alterdekim/game/dto/ProfilePageResult.java +++ b/src/main/java/com/alterdekim/game/dto/ProfilePageResult.java @@ -13,8 +13,8 @@ public class ProfilePageResult { private String username; private Long id; private String displayName; - private Integer games; - private Integer wins; + private Long games; + private Long wins; private Integer friends_cnt; private FriendFollowState follow_state; } diff --git a/src/main/java/com/alterdekim/game/entities/Game.java b/src/main/java/com/alterdekim/game/entities/Game.java new file mode 100644 index 0000000..f3a2f18 --- /dev/null +++ b/src/main/java/com/alterdekim/game/entities/Game.java @@ -0,0 +1,34 @@ +package com.alterdekim.game.entities; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name="games") +public class Game { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private Long userId; + + @Column(nullable = false) + private Boolean isDone; + + @Column(nullable = false) + private Boolean isWon; + + public Game(Long userId, Boolean isDone, Boolean isWon) { + this.userId = userId; + this.isDone = isDone; + this.isWon = isWon; + } +} diff --git a/src/main/java/com/alterdekim/game/repository/FriendRepository.java b/src/main/java/com/alterdekim/game/repository/FriendRepository.java index 79ba076..6b02813 100644 --- a/src/main/java/com/alterdekim/game/repository/FriendRepository.java +++ b/src/main/java/com/alterdekim/game/repository/FriendRepository.java @@ -16,9 +16,12 @@ public interface FriendRepository extends JpaRepository { @Query(value = "SELECT IF(f.firstUserId = :userId, f.secondUserId, f.firstUserId) FROM FriendStatus f WHERE (f.firstUserId = :userId OR f.secondUserId = :userId) AND f.status = 2") List getFriendsOfUserId(@Param("userId") Long userId); + @Query(value = "SELECT f.firstUserId FROM FriendStatus f WHERE f.secondUserId = :userId AND f.status = 1") + List getFollowersOfUserId(@Param("userId") Long userId); + @Transactional @Modifying - @Query(value = "DELETE FROM FriendStatus f WHERE ((f.firstUserId = :userId AND f.secondUserId = :friendId) OR (f.firstUserId = :friendId AND f.secondUserId = :userId)) AND f.status = 2") + @Query(value = "DELETE FROM FriendStatus f WHERE ((f.firstUserId = :userId AND f.secondUserId = :friendId) OR (f.firstUserId = :friendId AND f.secondUserId = :userId)) AND f.status > 0") void removeFriend(@Param("userId") Long userId, @Param("friendId") Long friendId); @Query(value = "SELECT f FROM FriendStatus f WHERE ((f.firstUserId = :userId AND f.secondUserId = :friendId) OR (f.firstUserId = :friendId AND f.secondUserId = :userId)) AND f.status = 1") diff --git a/src/main/java/com/alterdekim/game/repository/GamesRepository.java b/src/main/java/com/alterdekim/game/repository/GamesRepository.java new file mode 100644 index 0000000..43af0dd --- /dev/null +++ b/src/main/java/com/alterdekim/game/repository/GamesRepository.java @@ -0,0 +1,18 @@ +package com.alterdekim.game.repository; + +import com.alterdekim.game.entities.FriendStatus; +import com.alterdekim.game.entities.Game; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface GamesRepository extends JpaRepository { + + @Query(value = "SELECT COUNT(g) FROM Game g WHERE g.userId = :userId") + Long getGamesCount(@Param("userId") Long userId); + + @Query(value = "SELECT COUNT(g) FROM Game g WHERE g.userId = :userId AND g.isWon = true") + Long getWonGamesCount(@Param("userId") Long userId); +} diff --git a/src/main/java/com/alterdekim/game/security/SpringSecurity.java b/src/main/java/com/alterdekim/game/security/SpringSecurity.java index 09f490a..71aa712 100644 --- a/src/main/java/com/alterdekim/game/security/SpringSecurity.java +++ b/src/main/java/com/alterdekim/game/security/SpringSecurity.java @@ -40,6 +40,7 @@ public class SpringSecurity { .requestMatchers("/profile/**").hasAnyAuthority("ROLE_ADMIN") .requestMatchers("/api/**").hasAnyAuthority("ROLE_ADMIN") .requestMatchers("/friends").hasAnyAuthority("ROLE_ADMIN") + .requestMatchers("/followers").hasAnyAuthority("ROLE_ADMIN") .requestMatchers("/settings").hasAnyAuthority("ROLE_ADMIN") .requestMatchers("/static/**").permitAll() .requestMatchers("/access-denied").permitAll() diff --git a/src/main/java/com/alterdekim/game/service/FriendServiceImpl.java b/src/main/java/com/alterdekim/game/service/FriendServiceImpl.java index 5bc2918..ee6da6d 100644 --- a/src/main/java/com/alterdekim/game/service/FriendServiceImpl.java +++ b/src/main/java/com/alterdekim/game/service/FriendServiceImpl.java @@ -4,11 +4,13 @@ import com.alterdekim.game.dto.FriendFollowState; import com.alterdekim.game.entities.FriendStatus; import com.alterdekim.game.repository.FriendRepository; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; @Service +@Slf4j @AllArgsConstructor public class FriendServiceImpl { private final FriendRepository repository; @@ -17,6 +19,10 @@ public class FriendServiceImpl { return repository.getFriendsOfUserId(userId); } + public List getFollowersOfUserId(Long userId) { + return repository.getFollowersOfUserId(userId); + } + public void removeFriend(Long userId, Long friendId) { repository.removeFriend(userId, friendId); } @@ -39,11 +45,10 @@ public class FriendServiceImpl { public FriendFollowState getFriendState(Long userId, Long friendId) { FriendStatus fs = this.getFollow(userId, friendId); - if( fs != null ) { - if( fs.getFirstUserId().longValue() == userId.longValue() || - this.getFriend(userId, friendId) != null ) { - return FriendFollowState.FOLLOWED; - } + if( (fs != null && fs.getFirstUserId().longValue() == userId.longValue()) || + this.getFriend(userId, friendId) != null ) { + return FriendFollowState.FOLLOWED; + } else if( (fs != null && fs.getFirstUserId().longValue() != userId.longValue()) ) { return FriendFollowState.ACCEPT; } return FriendFollowState.NOT_FOLLOWED; diff --git a/src/main/java/com/alterdekim/game/service/GamesService.java b/src/main/java/com/alterdekim/game/service/GamesService.java new file mode 100644 index 0000000..54c800d --- /dev/null +++ b/src/main/java/com/alterdekim/game/service/GamesService.java @@ -0,0 +1,19 @@ +package com.alterdekim.game.service; + +import com.alterdekim.game.repository.GamesRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +public class GamesService { + private final GamesRepository repository; + + public Long getGamesCount(Long userId) { + return repository.getGamesCount(userId); + } + + public Long getWonGamesCount(Long userId) { + return repository.getWonGamesCount(userId); + } +} diff --git a/src/main/java/com/alterdekim/game/util/StringUtil.java b/src/main/java/com/alterdekim/game/util/StringUtil.java index e019fda..b67c3ff 100644 --- a/src/main/java/com/alterdekim/game/util/StringUtil.java +++ b/src/main/java/com/alterdekim/game/util/StringUtil.java @@ -8,6 +8,7 @@ public class StringUtil { for (int i = 0; i < message.length(); i++) { if (message.charAt(i) == '@') { int u = message.substring(i).indexOf(' ') + i; + if( u <= (i + 1) || u > message.length() ) return message; String username = message.substring(i + 1, u); User user = userService.findByUsername(username); if (user != null) { diff --git a/src/main/resources/static/javascript/friends.js b/src/main/resources/static/javascript/friends.js index 991a248..9b02914 100644 --- a/src/main/resources/static/javascript/friends.js +++ b/src/main/resources/static/javascript/friends.js @@ -17,4 +17,17 @@ function removeFriend(obj) { }).done(function() { $(obj).parent().parent().parent().remove(); }); +} + +function acceptFriend(obj) { + let friend_id = $(obj).attr("data-friend-id"); + $.ajax({ + method: "POST", + url: "/api/v1/friends/follow", + data: { + userId: friend_id + } + }).done(function() { + $(obj).parent().parent().parent().remove(); + }); } \ No newline at end of file diff --git a/src/main/resources/static/javascript/games.js b/src/main/resources/static/javascript/games.js index 85e8570..d7c8337 100644 --- a/src/main/resources/static/javascript/games.js +++ b/src/main/resources/static/javascript/games.js @@ -51,7 +51,14 @@ function joinRoom(obj) { } function takeInviteMessage(obj) { - // attr data-roomId + let roomId = $(obj).attr("data-roomId"); + $.ajax({ + url: "/api/v1/rooms/join/", + data: { + room_id: roomId + }, + method: "POST" + }); } function successPolling(data) { diff --git a/src/main/resources/static/javascript/profile.js b/src/main/resources/static/javascript/profile.js index 3f4f43b..73e6c43 100644 --- a/src/main/resources/static/javascript/profile.js +++ b/src/main/resources/static/javascript/profile.js @@ -9,4 +9,17 @@ function followUser(obj) { }).done(function() { window.location.reload(); }); +} + +function unfollowUser(obj) { + let uid = $(obj).attr('data-profile-id'); + $.ajax({ + method: "POST", + url: "/api/v1/friends/remove/", + data: { + friend_id: uid + } + }).done(function() { + window.location.reload(); + }); } \ No newline at end of file diff --git a/src/main/resources/templates/followers.html b/src/main/resources/templates/followers.html new file mode 100644 index 0000000..44ad874 --- /dev/null +++ b/src/main/resources/templates/followers.html @@ -0,0 +1,34 @@ + + + + + + + + + +
+

Friends > Followers

+
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/src/main/resources/templates/friends.html b/src/main/resources/templates/friends.html index 43f4547..48f89c2 100644 --- a/src/main/resources/templates/friends.html +++ b/src/main/resources/templates/friends.html @@ -8,7 +8,7 @@
-

Friends

+

Friends > Followers

diff --git a/src/main/resources/templates/settings.html b/src/main/resources/templates/settings.html index 446fdbe..38d1f53 100644 --- a/src/main/resources/templates/settings.html +++ b/src/main/resources/templates/settings.html @@ -43,7 +43,7 @@
-
+
Settings
-
+