This commit is contained in:
2024-04-27 08:56:51 +02:00
57 changed files with 974 additions and 822 deletions

View File

@ -19,7 +19,7 @@ export default class extends AbstractAuthenticatedView {
}
else
{
await client.matchmaking.start(this.onreceive.bind(this), this.ondisconnect.bind(this), this.gamemode_input.value, this.nb_players_input.value);
await client.matchmaking.start(this.onreceive.bind(this), this.ondisconnect.bind(this), this.game_type_input.value, this.nb_players_input.value);
this.button.innerHTML = lang.get("matchmakingStopSearch");
}
@ -34,10 +34,10 @@ export default class extends AbstractAuthenticatedView {
{
if (data.detail === "game_found")
{
if (this.gamemode_input.value == "pong")
navigateTo(`/games/${data.gamemode}/${data.game_id}`);
if (this.game_type_input.value == "pong")
navigateTo(`/games/${data.game_type}/${data.game_id}`);
else
navigateTo(`/games/${data.gamemode}/${data.game_id}`);
navigateTo(`/games/${data.game_type}/${data.game_id}`);
return;
}
this.display_data(data);
@ -51,7 +51,7 @@ export default class extends AbstractAuthenticatedView {
addEnterEvent()
{
[this.nb_players_input, this.gamemode_input].forEach((input) => {
[this.nb_players_input, this.game_type_input].forEach((input) => {
input.addEventListener('keydown', async ev => {
@ -74,13 +74,13 @@ export default class extends AbstractAuthenticatedView {
});
}
addChangeGameModeEvent()
addChangegame_typeEvent()
{
let nb_players_div = document.getElementById("nb-players-div");
this.gamemode_input.addEventListener("change", () => {
this.game_type_input.addEventListener("change", () => {
if (this.gamemode_input.value === "tictactoe")
if (this.game_type_input.value === "tictactoe")
{
nb_players_div.style.display = 'none';
this.nb_players_input.value = 2;
@ -96,7 +96,7 @@ export default class extends AbstractAuthenticatedView {
addEvents()
{
this.addEnterEvent();
this.addChangeGameModeEvent();
this.addChangegame_typeEvent();
this.addChangeNbPlayersEvent();
}
@ -104,7 +104,7 @@ export default class extends AbstractAuthenticatedView {
{
this.button = document.getElementById("toggle-search");
this.nb_players_input = document.getElementById("nb-players-input");
this.gamemode_input = document.getElementById("gamemode-input");
this.game_type_input = document.getElementById("game-type-input");
this.button.onclick = this.toggle_search.bind(this);
@ -117,12 +117,12 @@ export default class extends AbstractAuthenticatedView {
<div class='border border-2 rounded bg-light-subtle mx-auto p-2 col-md-7 col-lg-4'>
<h4 class='text-center fw-semibold mb-4' id="title">${lang.get("matchmakingTitle")}</h4>
<div>
<div class='form-floating mb-2' id='gamemode-div'>
<select class='form-control' id='gamemode-input'>
<div class='form-floating mb-2' id='game_type-div'>
<select class='form-control' id='game-type-input'>
<option value='pong'>Pong</option>
<option value='tictactoe'>ticTacToe</option>
</select>
<label for='gamemode-input'>${lang.get("gamemodeChoice")}</label>
<label for='game-type-input'>${lang.get("game_typeChoice")}</label>
</div>
<div class='form-floating mb-2' id='nb-players-div'>
<input type='number' min='2' value='2' max='4' class='form-control' id='nb-players-input' placeholder='${lang.get("matchmakingNbPlayers")}'>

View File

@ -8,7 +8,7 @@ export default class extends AbstractView {
}
setTitle() {
document.title = `${this.username} - Profile`;
document.title = this.titleKey;
}
async postInit()
@ -16,99 +16,48 @@ export default class extends AbstractView {
if (!this.profile)
return 404;
this.userId = this.profile.id;
await this.blockButton();
await this.friendButton();
client.notice.rewrite_profile = async () => {
await this.profile.getFriend();
await this.profile.getBlock();
await this.friendButton();
};
}
async blockButton() {
// Block option
if (await client.isAuthenticated() === false)
if (this.profile.id === client.me.id)
return;
if (client.me.id != this.userId) {
let block = document.getElementById("block");
if (block == undefined) {
block = document.createElement("p");
// this.info.appendChild(block);
}
const addFriendButton = document.getElementById('addFriendButton'),
removeFriendButton = document.getElementById('removeFriendButton'),
blockButton = document.getElementById('blockButton'),
unblockButton = document.getElementById('unblockButton');
block.id = "block";
block.onclick = async () => {
if (!this.profile.isBlocked)
await client.profiles.block(this.userId);
else
await client.profiles.deblock(this.userId);
this.profile = await client.profiles.getProfile(this.username);
this.loadFriendshipStatus();
if (this.profile.isBlocked)
unblockButton.classList.remove('d-none');
else
blockButton.classList.remove('d-none');
this.blockButton();
};
if (this.profile.isBlocked)
block.textContent = lang.get('profileUnblock', 'Unblock');
else
block.textContent = lang.get('profileBlock', 'Block');
}
addFriendButton.onclick = _ => this.addFriend();
removeFriendButton.onclick = _ => this.removeFriend();
unblockButton.onclick = _ => this.unblockUser();
blockButton.onclick = _ => this.blockUser();
}
async friendButton() {
if (await client.isAuthenticated() === false)
return;
loadFriendshipStatus() {
const addFriendButton = document.getElementById('addFriendButton'),
removeFriendButton = document.getElementById('removeFriendButton');
if (client.me.id != this.userId) {
let yes = document.getElementById("yes") || document.createElement("p");
let no = document.getElementById("no") || document.createElement("p");
let friend = document.getElementById("friend") || document.createElement("p");
if (client.notice.data.asker.includes(this.userId)) {
if (friend)
friend.remove();
yes.id = "yes";
yes.textContent = lang.get('profileAcceptRequest', 'Accept Friend');
yes.onclick = async () => {
client.notice.accept_friend(this.userId);
};
no.id = "no";
no.textContent = lang.get('profileDenyRequest', 'Decline Friend');
no.onclick = async () => {
client.notice.refuse_friend(this.userId);
};
// this.info.appendChild(yes);
// this.info.appendChild(document.createTextNode(" "));
// this.info.appendChild(no);
}
else {
if (yes && no)
yes.remove(); no.remove();
friend.id = "friend";
friend.onclick = async () => {
if (this.profile.isFriend)
await client.notice.remove_friend(this.userId);
else
await client.notice.ask_friend(this.userId);
await client.profiles.getProfile(this.username);
this.friendButton();
};
if (this.profile.isFriend)
friend.textContent = lang.get('profileRemoveFriend', 'Remove Friend');
else {
friend.textContent = lang.get('profileAddFriend', 'Ask Friend');
}
// this.info.appendChild(friend);
}
if (this.profile.hasIncomingRequest) {
removeFriendButton.classList.add('d-none');
addFriendButton.classList.remove('d-none');
addFriendButton.innerHTML = 'Accept Request';
} else if (this.profile.hasOutgoingRequest) {
addFriendButton.classList.add('d-none');
removeFriendButton.classList.remove('d-none');
removeFriendButton.classList.replace('btn-danger', 'btn-secondary');
removeFriendButton.innerHTML = 'Cancel Request';
} else if (this.profile.isFriend) {
addFriendButton.classList.add('d-none');
removeFriendButton.classList.remove('d-none');
removeFriendButton.classList.replace('btn-secondary', 'btn-danger');
removeFriendButton.innerHTML = 'Remove Friend';
} else {
addFriendButton.innerHTML = 'Add Friend';
removeFriendButton.classList.add('d-none');
addFriendButton.classList.remove('d-none');
}
}
@ -118,19 +67,94 @@ export default class extends AbstractView {
if (!this.profile)
return '';
const logged = await client.isAuthenticated();
return `
<div class='mb-3' id='profileInfo'>
<h1>${this.username}</h1>
<a href=${this.profile.avatar} target='_blank'>
<img class='img-thumbnail' src=${this.profile.avatar} style='width:auto; max-height:20vh; min-height:10vh'>
</a>
</div>
<div>
<button class='btn btn-sm btn-success ${logged ? '' : 'd-none'}' id='addFriendButton'>Add Friend</button>
<button class='btn btn-sm btn-danger ${logged ? '' : 'd-none'}' id='removeFriendButton'>Remove Friend</button>
</div>
`;
<div>
<div class='mb-3' id='profileInfo'>
<h1>${this.username}</h1>
<a href=${this.profile.avatar} target='_blank'>
<img class='img-thumbnail' src=${this.profile.avatar} style='width:auto; max-height:20vh; min-height:10vh'>
</a>
</div>
<div>
<button class='btn btn-sm btn-success d-none' id='addFriendButton'>Add Friend</button>
<button class='btn btn-sm btn-danger d-none' id='removeFriendButton'>Remove Friend</button>
<button class='btn btn-sm btn-danger d-none' id='blockButton'>Block</button>
<button class='btn btn-sm btn-secondary d-none' id='unblockButton'>Unblock</button>
</div>
</div>
`;
}
async addFriend() {
const removeFriendButton = document.getElementById('removeFriendButton');
const response = await client._post(`/api/profiles/friends/${this.profile.id}`);
const body = await response.json();
console.log(body);
if (response.ok) {
removeFriendButton.classList.remove('d-none');
document.getElementById('addFriendButton').classList.add('d-none');
}
if (response.status === 200) {
removeFriendButton.innerHTML = 'Cancel Request';
removeFriendButton.classList.replace('btn-danger', 'btn-secondary');
client.me.outgoingFriendRequests.push(this.profile);
this.profile.hasOutgoingRequest = true;
} else if (response.status === 201) {
removeFriendButton.innerHTML = 'Remove Friend';
removeFriendButton.classList.replace('btn-secondary', 'btn-danger');
this.profile.friend = true;
this.profile.hasIncomingRequest = false;
client.me.incomingFriendRequests = client.me.incomingFriendRequests.filter(profile => profile.id !== this.profile.id);
client.me.friendList.push(this.profile);
}
}
async removeFriend() {
const addFriendButton = document.getElementById('addFriendButton');
const response = await client._delete(`/api/profiles/friends/${this.profile.id}`);
const body = await response.json();
console.log(body);
if (response.ok) {
addFriendButton.innerHTML = 'Add Friend';
addFriendButton.classList.remove('d-none');
document.getElementById('removeFriendButton').classList.add('d-none');
}
if (response.status === 200) {
this.profile.hasOutgoingRequest = false;
client.me.outgoingFriendRequests = client.me.outgoingFriendRequests.filter(profile => profile.id !== this.profile.id);
} else if (response.status === 201) {
this.profile.isFriend = false;
client.me.friendList = client.me.friendList.filter(friend => friend.id !== this.profile.id);
}
}
async blockUser() {
const response = await client._post(`/api/profiles/block/${this.profile.id}`);
const body = await response.json();
console.log(body);
if (response.ok) {
document.getElementById('blockButton').classList.add('d-none');
document.getElementById('unblockButton').classList.remove('d-none');
client.me.blockedUsers.push(this.profile);
this.profile.isBlocked = true;
}
}
async unblockUser() {
const response = await client._delete(`/api/profiles/block/${this.profile.id}`);
const body = await response.json();
console.log(body);
if (response.ok) {
document.getElementById('unblockButton').classList.add('d-none');
document.getElementById('blockButton').classList.remove('d-none');
client.me.blockedUsers = client.me.blockedUsers.filter(profile => profile.id !== this.profile.id);
this.profile.isBlocked = false;
}
}
}

View File

@ -19,7 +19,6 @@ export class TicTacToeOnlineView extends AbstractView
this.Morpion = new TicTacToe(this.height, this.width, 60, 60, document.getElementById("Morpion"), this.game_id);
this.Morpion.DrawSuperMorpion();
await this.Morpion.init();
this.Morpion.setOutline();
}
async leavePage()

View File

@ -10,7 +10,6 @@ export default class extends AbstractAuthenticatedView
async postInit() {
await client.logout();
await client.notice.disconnect();
navigateTo(this.lastPageUrl);
}
}

View File

@ -16,10 +16,9 @@ export default class extends AbstractAuthenticatedView
if (name.length == 0)
name = lang.get("TournamentCreateTournamentName");
console.log(name);
let nb_players = document.getElementById("nb-players-input").value;
let nb_participant = document.getElementById("nb-participant-input").value;
let response = await client.tournaments.createTournament(nb_players, name);
let response = await client.tournaments.createTournament(nb_participant, name);
let response_data = await response.json();
let id = response_data.id;
@ -29,7 +28,7 @@ export default class extends AbstractAuthenticatedView
return;
}
clearIds("innerHTML", ["name", "nb_players"]);
clearIds("innerHTML", ["name", "nb_participants"]);
fill_errors(response_data, "innerHTML");
}
@ -50,9 +49,16 @@ export default class extends AbstractAuthenticatedView
<span class='text-danger' id='name'></span>
</div>
<div class='form-floating mb-2'>
<input type='number' class='form-control' min='2' value='4' id='nb-players-input' placeholder='${lang.get("TournamentCreateNbPlayer")}'>
<label for='nb-players-input' id='nb-players-label'>${lang.get("TournamentCreateNbPlayer")}</label>
<span class='text-danger' id='nb_players'></span>
<select class='form-control' id="nb-participant-input">
<option value="2">2</option>
<option value="4">4</option>
<option value="8">8</option>
<option value="16">16</option>
<option value="32">32</option>
<option value="64">64</option>
</select>
<label for='nb-participant-input' id='nb-participant-label'>${lang.get("TournamentCreateNbPlayer")}</label>
<span class='text-danger' id='nb_participants'></span>
</div>
<div class='d-flex'>
<button type='button' class='btn btn-primary mt-3 mb-2 mx-2' id='create-button'>${lang.get("TournamentCreateButton")}</button>

View File

@ -3,6 +3,10 @@ import { Tourmanent } from "../../api/tournament/Tournament.js";
import {client, navigateTo} from "../../index.js";
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
const TEXT_CONVENTION = {
"error": "[ERROR]"
}
export default class extends AbstractAuthenticatedView
{
constructor(params)
@ -13,44 +17,49 @@ export default class extends AbstractAuthenticatedView
pressButton()
{
this.tournament.toggle_participation();
this.tournament.setParticipation(!this.tournament.isParticipating);
this.updateParticipating()
}
async receive(data)
updateParticipating()
{
if (data.detail === "update_participants")
document.getElementById("nb_participants").innerText = `${data.participants} / ${this.tournament.nb_participants}`;
if (data.detail === "go_to")
navigateTo(data.url);
if (data.detail === "is_participant")
this.updateParticipating(data.is_participant);
if (data.detail === "error")
document.getElementById("display").innerText = data.error_message;
}
async updateParticipating(state)
{
document.getElementById("button").value = state ? `Leave ${this.tournament.name}` : `Join ${this.tournament.name}`;
document.getElementById("display").innerText = state ? "You are a particpant" : "You are not a participant";
}
/**
*
* @param {[Profile]} oldParticipantsList
* @param {[Profile]} currentParticipantsList
*/
async onParticipantsUpdate(oldParticipantsList, currentParticipantsList)
{
document.getElementById("button").value = this.tournament.isParticipating ? `Leave ${this.tournament.name}` : `Join ${this.tournament.name}`;
document.getElementById("display").innerText = this.tournament.isParticipating ? "You are a particpant" : "You are not a participant";
}
async onDisconnect(event)
{
}
async onError(data)
{
this.addChatMessage(`${TEXT_CONVENTION} data.error_message`);
}
async onFinish()
{
document.getElementById("state").innerText = "finished"
}
async onStart()
{
document.getElementById("state").innerText = "started"
}
async onGoTo(data)
{
await navigateTo(`/games/pong/${data.game_id}`)
}
async onAddParticipant(nb_participants)
{
document.getElementById("nb_participants").innerText = nb_participants;
}
async onDelParticipant(nb_participants)
{
document.getElementById("nb_participants").innerText = nb_participants;
}
async postInit()
@ -63,25 +72,32 @@ export default class extends AbstractAuthenticatedView
if (this.tournament === null)
return 404;
this.tournament.join(this.onParticipantsUpdate.bind(this), this.onError.bind(this), this.onDisconnect.bind(this));
this.tournament.join(this.onAddParticipant, this.onDelParticipant, this.onStart, this.onFinish, this.onError, this.onGoTo, this.onDisconnect);
let button = document.getElementById("button");
button.onclick = this.pressButton.bind(this);
document.getElementById("name").innerText = this.tournament.name;
document.getElementById("nb_participants").innerText = this.tournament.nb_participants;
document.getElementById("nb_participants").innerText = this.tournament.participantList.length;
document.getElementById("expected_nb_participants").innerText = this.tournament.nb_participants;
document.getElementById("round").innerText = this.tournament.round;
document.getElementById("state").innerText = this.tournament.state;
if (this.tournament.started === false)
button.disabled = false;
console.log(this.tournament);
this.chat = document.getElementById("chat");
console.log(this.tournament);
this.display_tree_tournament(this.tournament.nb_participants, this.tournament.participantList);
}
addChatMessage(message)
{
this.chat.innerText += message;
}
async display_tree_tournament(nb_participants, participants) {
const svg = document.getElementById('tree');
@ -137,15 +153,25 @@ export default class extends AbstractAuthenticatedView
<td id="nb_participants">Loading...</td>
</tr>
<tr>
<td>status</td>
<td>Expected number of participants</td>
<td id="expected_nb_participants">Loading...</td>
</tr>
<tr>
<td>state</td>
<td id="state">Loading...</td>
</tr>
</tbody>
</table>
<input type="button" id="button" value="Join tournament" disabled>
<<<<<<< HEAD
<br>
<svg id="tree" height="3000" width="3000">
</svg>
=======
<span id="display"></span>
<textarea id="chat" rows="4" cols="50" readonly>
</textarea>
>>>>>>> 55d29d5763f22f136d2b4bae6464463acb514a5c
`;
}
}