Followers page / Games stats / Chat bugfix
This commit is contained in:
parent
8408eb874e
commit
ccc87d57f4
@ -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<FriendResult> {
|
||||
|
||||
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<FriendResult> {
|
||||
List<FriendResult> 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());
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -11,4 +11,5 @@ public class FriendResult {
|
||||
private FriendState action;
|
||||
private Long id;
|
||||
private String username;
|
||||
private Long avatarId;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
34
src/main/java/com/alterdekim/game/entities/Game.java
Normal file
34
src/main/java/com/alterdekim/game/entities/Game.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -16,9 +16,12 @@ public interface FriendRepository extends JpaRepository<FriendStatus, Long> {
|
||||
@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<Long> getFriendsOfUserId(@Param("userId") Long userId);
|
||||
|
||||
@Query(value = "SELECT f.firstUserId FROM FriendStatus f WHERE f.secondUserId = :userId AND f.status = 1")
|
||||
List<Long> 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")
|
||||
|
@ -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<Game, Long> {
|
||||
|
||||
@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);
|
||||
}
|
@ -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()
|
||||
|
@ -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<Long> 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;
|
||||
|
19
src/main/java/com/alterdekim/game/service/GamesService.java
Normal file
19
src/main/java/com/alterdekim/game/service/GamesService.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
@ -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) {
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
34
src/main/resources/templates/followers.html
Normal file
34
src/main/resources/templates/followers.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/head}"></th:block>
|
||||
<link rel="stylesheet" href="/static/css/friends.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/navbar}"></th:block>
|
||||
|
||||
<div class="container mt-5 block">
|
||||
<h2><a href="/friends">Friends</a> > Followers</h2>
|
||||
<div class="friends-list">
|
||||
<th:block th:each="friend: ${friends}">
|
||||
<div class="friends-list-one">
|
||||
<a th:href="${friend.href}">
|
||||
<div class="friends-list-one-avatar" th:style="${friend.avatar}"></div>
|
||||
</a>
|
||||
<div class="friends-list-one-info">
|
||||
<div class="friends-list-one-info-nick">
|
||||
<a th:href="${friend.href}" th:text="${friend.displayName}"></a>
|
||||
</div>
|
||||
<div class="friends-list-one-info-actions" style="display: none;">
|
||||
<button onClick="acceptFriend(this)" class="btn btn-primary btn-sm" th:data-friend-id="${friend.id}">Accept</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<th:block th:insert="~{fragments/essentials}"></th:block>
|
||||
<script src="/static/javascript/friends.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -8,7 +8,7 @@
|
||||
<th:block th:insert="~{fragments/navbar}"></th:block>
|
||||
|
||||
<div class="container mt-5 block">
|
||||
<h2>Friends</h2>
|
||||
<h2>Friends > <a href="/followers">Followers</a></h2>
|
||||
<div class="friends-list">
|
||||
<th:block th:each="friend: ${friends}">
|
||||
<div class="friends-list-one">
|
||||
|
@ -43,7 +43,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block" id="security" style="margin-top: 15px;">
|
||||
<!-- <div class="block" id="security" style="margin-top: 15px;">
|
||||
<div class="title">Security</div>
|
||||
<div class="block-content">
|
||||
<div class="grid">
|
||||
@ -69,25 +69,25 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
<div class="g-col-4">
|
||||
<div class="block" style="margin-top: 15px;">
|
||||
<div class="title">Settings</div>
|
||||
<div class="block-content" style="display: block;">
|
||||
<a href="#profile" class="menu-item _selected">Profile</a>
|
||||
<a href="#security" class="menu-item">Security</a>
|
||||
<a href="#privacy" class="menu-item">Privacy</a>
|
||||
<!--<a href="#security" class="menu-item">Security</a>
|
||||
<a href="#privacy" class="menu-item">Privacy</a>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block" style="margin-top: 15px;">
|
||||
<!-- <div class="block" style="margin-top: 15px;">
|
||||
<div class="title">Data</div>
|
||||
<div class="block-content" style="display: block;">
|
||||
<a href="#blacklist" class="menu-item">Black list</a>
|
||||
<a href="#notes" class="menu-item">Notes</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user