feat(DevWeb): Create WebsocketToolkit.js

This commit is contained in:
Lucàs
2024-04-23 20:06:17 +02:00
parent 5bc33f7754
commit 2f9d2546fb
8 changed files with 137 additions and 118 deletions
+1 -1
View File
@@ -91,7 +91,7 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId> <artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version> <version>3.3.2</version>
</plugin> </plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>16</source><target>16</target></configuration></plugin>
</plugins> </plugins>
</build> </build>
</project> </project>
@@ -1,6 +1,10 @@
package uppa.project.json.websocket; package uppa.project.json.websocket;
import com.google.gson.Gson;
public class Message { public class Message {
private final static Gson gson = new Gson();
private final String type; private final String type;
private final String data; private final String data;
@@ -17,6 +21,10 @@ public class Message {
return data; return data;
} }
public String toJson() {
return gson.toJson(this);
}
@Override @Override
public String toString() { public String toString() {
return "Message{" + "type=" + type + ", data=" + data + '}'; return "Message{" + "type=" + type + ", data=" + data + '}';
@@ -5,45 +5,50 @@ import jakarta.websocket.OnClose;
import jakarta.websocket.OnError; import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage; import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen; import jakarta.websocket.OnOpen;
import jakarta.websocket.RemoteEndpoint;
import jakarta.websocket.Session; import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint; import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.User; import uppa.project.database.pojo.User;
import uppa.project.json.websocket.Message; import uppa.project.json.websocket.Message;
@ServerEndpoint(value = "/ws/connected-users") @ServerEndpoint(value = "/ws/users/{user_id}")
public class ConnectedUsersWS { public class ConnectedUsersWS {
public static final HashMap<Session, User> connections = new HashMap<>(); public static final HashMap<Session, User> users = new HashMap<>();
private static final Gson gson = new Gson();
@OnOpen @OnOpen
public void onOpen(Session session) {} public void onOpen(Session session, @PathParam("user_id") String userId) throws DAOException {
Message message;
final DAO<User> userDAO = new Game_JPA_DAO_Factory().getDAOUser();
private void broadcastConnectedUsers() { int id = Integer.parseInt(userId);
Gson gson = new Gson(); User user = userDAO.findById(id);
User[] connectedUsers = connections.values().toArray(new User[0]);
Message websocketObject = new Message("userList", gson.toJson(connectedUsers)); // Send the new user to all connected users
String message = gson.toJson(websocketObject); message = new Message("addUser", gson.toJson(new SimpleUser(user)));
broadcast(message.toJson());
for (Session session : connections.keySet()) { // Send all connected users to the new user
RemoteEndpoint.Basic remote = session.getBasicRemote(); users.put(session, user);
try { ArrayList<SimpleUser> connectedUsers = new ArrayList<>();
remote.sendText(message); for (User u : users.values()) connectedUsers.add(new SimpleUser(u));
} catch (IOException e) { message = new Message("init", gson.toJson(connectedUsers));
e.printStackTrace(); session.getAsyncRemote().sendText(message.toJson());
}
}
} }
@OnClose @OnClose
public void onClose(Session session) { public void onClose(Session session) {
connections.remove(session); users.remove(session);
// Update connected users list Message message = new Message("removeUser", gson.toJson(new SimpleUser(users.get(session))));
broadcastConnectedUsers(); broadcast(message.toJson());
} }
@OnError @OnError
@@ -53,13 +58,26 @@ public class ConnectedUsersWS {
@OnMessage @OnMessage
public void onMessage(String message, Session session) { public void onMessage(String message, Session session) {
Gson gson = new Gson(); // Do nothing
Message websocketMessage = gson.fromJson(message, Message.class); }
if (websocketMessage.getType().equals("linkUserSession")) { private static void broadcast(String message) {
User user = gson.fromJson(websocketMessage.getData(), User.class); for (Session session : users.keySet()) {
connections.put(session, user); try {
broadcastConnectedUsers(); session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class SimpleUser {
public int id;
public String username;
public SimpleUser(User user) {
this.id = user.getId().intValue();
this.username = user.getUsername();
} }
} }
} }
@@ -1,95 +1,63 @@
<jsp:useBean id="user" scope="session" type="uppa.project.database.pojo.User"/>
<%@tag description="component/connected-user-list" pageEncoding="UTF-8" %> <%@tag description="component/connected-user-list" pageEncoding="UTF-8" %>
<%@tag import="com.google.gson.Gson" %> <%@tag import="com.google.gson.Gson" %>
<%@tag import="uppa.project.database.pojo.User" %>
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %> <%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
<%@attribute name="anonymous"%>
<table id="connected-user-list" class="table is-fullwidth"> <table id="connected-user-list" class="table is-fullwidth">
<thead> <thead>
<tr> <tr>
<th>Utilisateur</th> <th>Utilisateur</th>
<%-- <th>Nombre de parties</th>--%>
<%-- <th>Victoires (%)</th>--%>
<%-- <th>Clics corrects (%)</th>--%>
<%-- <th>Clics rapides (%)</th>--%>
<%-- <th>Action</th>--%>
</tr> </tr>
</thead> </thead>
<tbody></tbody> <tbody></tbody>
</table> </table>
<script defer type="module"> <script defer type="module">
const tbodyElement = document.querySelector('#connected-user-list tbody'); import WebsocketToolkit from "${pageContext.request.contextPath}/static/js/WebsocketToolkit.js";
// effacer ce qu'il y a apres /project_war_exploded let users = [];
const url = new URL(window.location.href); function updateUsers() {
url.pathname = "${pageContext.request.contextPath}/ws/connected-users"; const table = document.querySelector('#connected-user-list tbody');
url.protocol = "ws:"
const websocket = new WebSocket(url); // Clear the table
table.innerHTML = '';
<% // Add the users to the table
Gson gson = new Gson();
User user = (User) request.getSession().getAttribute("user");
%>
websocket.onopen = () => {
const linkUserSession = {
type: 'linkUserSession',
data: JSON.stringify(<%= gson.toJson(user) %>)
}
websocket.send(JSON.stringify(linkUserSession));
}
websocket.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'userList') {
const users = JSON.parse(data.data);
updateUserList(users);
}
}
websocket.onclose = () => {}
websocket.onerror = (error) => console.error(error);
function updateUserList(users) {
tbodyElement.innerHTML = '';
users.forEach(user => { users.forEach(user => {
const trElement = document.createElement('tr'); const tr = document.createElement('tr');
const tdElement = [ const td = document.createElement('td');
document.createElement('td'),
// document.createElement('td'),
// document.createElement('td'),
// document.createElement('td'),
// document.createElement('td'),
// document.createElement('td')
];
// const buttonElement = document.createElement('button');
tdElement[0].textContent = user.username; td.dataset.id = user.id;
// tdElement[1].textContent = user.nbPlayedGames; td.textContent = user.username;
// tdElement[2].textContent = user.WinRate + '%';
// tdElement[3].textContent = user.rightClickPercentRate + '%';
// tdElement[4].textContent = user.rapidClickPercentRate + '%';
// If it's not the current user, we can display the button tr.appendChild(td);
<%--if (user.id !== <%= user.getId() %>) {--%> table.appendChild(tr);
<%-- buttonElement.classList.add('button', 'is-light');--%>
<%-- buttonElement.textContent = 'Inviter';--%>
<%-- // TODO Ajouter l'événement click--%>
<%--}--%>
// tdElement[5].appendChild(buttonElement);
trElement.appendChild(tdElement[0]);
// trElement.appendChild(tdElement[1]);
// trElement.appendChild(tdElement[2]);
// trElement.appendChild(tdElement[3]);
// trElement.appendChild(tdElement[4]);
// trElement.appendChild(tdElement[5]);
tbodyElement.appendChild(trElement);
}); });
} }
// Create a new WebSocket
const url = new URL(window.location.href);
url.pathname = "${pageContext.request.contextPath}/ws/users/${user.id}";
url.protocol = "ws:"
const ws = new WebsocketToolkit(url);
ws.onOpen(() => console.log("Connected to the server"));
ws.onMessage("init", (data) => {
users = data;
updateUsers();
});
ws.onMessage("addUser", (data) => {
users.push(data);
updateUsers();
});
ws.onMessage("removeUser", (data) => {
users = users.filter(user => user.id !== data.id);
updateUsers();
});
ws.onError((error) => console.error(error));
ws.onClose(() => console.log("Disconnected from the server"));
</script> </script>
@@ -6,13 +6,13 @@
<% if (session.getAttribute("user") != null) { %> <% if (session.getAttribute("user") != null) { %>
<a class="navbar-item" href="${pageContext.request.contextPath}/lobby"> <a class="navbar-item" href="${pageContext.request.contextPath}/lobby">
<img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260"> <img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260" alt="Logo">
</a> </a>
<% } else { %> <% } else { %>
<a class="navbar-item" href="${pageContext.request.contextPath}/"> <a class="navbar-item" href="${pageContext.request.contextPath}/">
<img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260"> <img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260" alt="Logo">
</a> </a>
<% } %> <% } %>
@@ -0,0 +1,13 @@
export default class Message {
constructor(rawMessage) {
// Parse the message
const message = JSON.parse(rawMessage);
message.data = JSON.parse(message.data);
console.log(message);
// Set the message properties
this.type = message.type;
this.data = message.data;
}
}
@@ -0,0 +1,31 @@
import Message from "./Message.js";
export default class WebsocketToolkit {
action = {}
constructor(url) {
this.url = url;
this.ws = new WebSocket(url);
}
onOpen(callback) {
this.ws.onopen = callback;
}
onMessage(type, callback) {
this.action[type] = callback;
this.ws.onmessage = (event) => {
const message = new Message(event.data);
this.action[message.type](message.data)
};
}
onClose(callback) {
this.ws.onclose = callback;
}
onError(callback) {
this.ws.onerror = callback;
}
}
@@ -1,19 +0,0 @@
const nbColorsElement = document.getElementById("nbColors");
const nbValuesElement = document.getElementById("nbValues");
const nbRoundsElement = document.getElementById("nbRounds")
/**
* Mise à jour du nombre de rounds max en fonction du nombre de couleurs et de valeurs séléctionnés
*/
function updateOnChange() {
nbRoundsElement.max = nbColorsElement.value * nbValuesElement.value;
nbRoundsElement.value =
(nbRoundsElement.value > nbRoundsElement.max)
? nbRoundsElement.max
: nbRoundsElement.value
;
}
nbColorsElement.addEventListener("change", updateOnChange);
nbValuesElement.addEventListener("change", updateOnChange);