Merge pull request 'update malouze cooking' (#6) from main into malouze-cooking

Reviewed-on: https://codeberg.org/adrien-lsh/ft_transcendence/pulls/6
This commit is contained in:
kbz_8
2024-02-14 17:53:57 +00:00
91 changed files with 2665 additions and 1360 deletions

View File

@ -19,6 +19,10 @@ export default class extends AbstractView {
document.getElementById('stopGameButton').onclick = this.stopGame.bind(this);
}
async leavePage() {
this.game?.cleanup();
}
startGame() {
if (this.game == null) {
document.getElementById('startGameButton').innerHTML = 'Reset Game';
@ -26,6 +30,7 @@ export default class extends AbstractView {
}
else {
document.getElementById('app').removeChild(this.game.canvas);
document.getElementById('app').removeChild(this.game.scoresDisplay);
this.game.cleanup();
this.game = new Game;
}

View File

@ -13,7 +13,7 @@ export default class extends AbstractView
this.my_player = undefined;
}
keyStretchHandler(event)
keyReleaseHandler(event)
{
const idx = this.keys_pressed.indexOf(event.key);
if (idx != -1)
@ -26,7 +26,7 @@ export default class extends AbstractView
this.keys_pressed.push(event.key);
}
draw()
render_game()
{
const canva = document.getElementById('canva');
@ -40,36 +40,39 @@ export default class extends AbstractView
ctx.beginPath();
this.game.draw(ctx);
this.game.render(ctx);
ctx.strokeStyle = "#000000";
ctx.lineWidth = 10;
ctx.lineWidth = 1;
ctx.stroke();
}
render_game()
render()
{
let loop_id = setInterval(() => {
if (this.game === undefined)
clearInterval(loop_id);
if (this.my_player)
this.my_player.update_paddle(this.keys_pressed);
this.draw();
this.render_game();
this.game?.time.new_frame();
//clearInterval(loop_id);
// 1 sec fps
}, 1000 / 60);
}
register_key()
{
document.addEventListener('keydown', this.keyPressHandler.bind(this));
document.addEventListener('keyup', this.keyStretchHandler.bind(this));
this.keyPressHandler = this.keyPressHandler.bind(this);
this.keyReleaseHandler = this.keyReleaseHandler.bind(this);
document.addEventListener('keydown', this.keyPressHandler);
document.addEventListener('keyup', this.keyReleaseHandler);
}
unregister_key()
{
document.removeEventListener('keydown', this.keyPressHandler);
document.removeEventListener('keyup', this.keyStretchHandler);
document.removeEventListener('keyup', this.keyReleaseHandler);
}
async join_game()
@ -99,7 +102,7 @@ export default class extends AbstractView
this.register_key()
this.render_game();
this.render();
}
async update_game_state()

View File

@ -1,18 +1,19 @@
import AbstractAuthentificateView from "./abstracts/AbstractAuthentifiedView.js";
import { lang } from "../index.js";
import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthentificateView {
export default class extends AbstractAuthenticatedView {
constructor(params) {
super(params, "Home");
super(params, 'homeWindowTitle');
this.redirect_url = "/login"
}
async getHtml() {
return /* HTML */ `
<h1>HOME</h1>
<a href="/matchmaking" class="nav__link" data-link>Play a game</a>
<a href="/games/offline" class="nav__link" data-link>Play offline</a>
<a href="/me" class="nav__link" data-link>Me</a>
<a href="/logout" class="nav__link" data-link>Logout</a>
<h1>${lang.get('homeTitle', 'Home')}</h1>
<a href="/matchmaking" data-link>${lang.get('homeOnline', 'Play online')}</a>
<a href="/games/offline" data-link>${lang.get('homeOffline', 'Play offline')}</a>
<a href="/settings" data-link>${lang.get('homeSettings', 'Settings')}</a>
<a href="/logout" data-link>${lang.get('homeLogout', 'Logout')}</a>
`;
}
}

View File

@ -1,8 +1,8 @@
import { client, navigateTo } from "../index.js";
import { clear, fill_errors } from "../utils/formUtils.js";
import AbstractAuthentifiedView from "./abstracts/AbstractAuthentifiedView.js";
import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthentifiedView {
export default class extends AbstractAuthenticatedView {
constructor(params)
{
super(params, "Matchmaking");

View File

@ -1,13 +1,15 @@
import AbstractView from "./abstracts/AbstractView.js";
import { lang } from '../index.js'
export default class extends AbstractView {
constructor(params) {
super(params, "Dashboard");
super(params, '404WindowTitle');
}
async getHtml() {
return `
<h1>404 Bozo</h1>
<img src="https://media.giphy.com/media/pm0BKtuBFpdM4/giphy.gif">
<p>Git gud</p>
`;
}

View File

@ -1,25 +1,26 @@
import AbstractView from "./abstracts/AbstractView.js";
import { client } from "../index.js"
import { client, lang } from "../index.js"
export default class extends AbstractView {
constructor(params) {
super(params, params.username);
this.username = params.username;
super(params, decodeURI(params.username));
this.username = decodeURI(params.username);
}
async postInit()
{
this.profile = await client.profiles.getProfile(this.username);
if (this.profile === null)
return 404;
this.userId = this.profile.id;
this.user_id = this.profile.id;
this.info = document.getElementById("info");
// Username
let username = document.createElement("a");
username.id = "username";
username.appendChild(document.createTextNode(this.profile.username));
username.appendChild(document.createTextNode(this.username));
this.info.appendChild(username);
this.info.appendChild(document.createElement("br"));
@ -31,30 +32,97 @@ export default class extends AbstractView {
this.info.appendChild(avatar);
await this.blockButton();
await this.friendButton();
client.notice.rewrite_profile = async () => {
let result = await this.profile.getFriend();
await this.profile.getBlock()
await this.friendButton();
}
}
async blockButton() {
// Block option
if (await client.isAuthentificate() === false)
if (await client.isAuthenticated() === false)
return;
if (client.me.id != this.userId) {
let block = document.getElementById("block") || document.createElement("a");
if (client.me.id != this.user_id) {
let block = document.getElementById("block");
if (block == undefined) {
block = document.createElement("p");
this.info.appendChild(block);
}
block.id = "block";
block.innerText = "";
block.onclick = async () => {
if (!this.profile.isBlocked)
await client.profiles.block(this.userId);
await client.profiles.block(this.user_id);
else
await client.profiles.deblock(this.userId);
await client.profiles.deblock(this.user_id);
this.profile = await client.profiles.getProfile(this.username);
this.blockButton();
};
if (this.profile.isBlocked)
block.appendChild(document.createTextNode("Deblock"));
block.textContent = lang.get('profileUnblock', 'Unblock');
else
block.appendChild(document.createTextNode("Block"));
this.info.appendChild(block);
block.textContent = lang.get('profileBlock', 'Block');
}
}
async friendButton() {
if (await client.isAuthenticated() === false)
return;
if (client.me.id != this.user_id) {
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.user_id)) {
if (friend)
friend.remove();
yes.id = "yes";
yes.textContent = lang.get('profileAcceptRequest', 'Accept Friend');
yes.onclick = async () => {
client.notice.accept_friend(this.user_id);
}
no.id = "no";
no.textContent = lang.get('profileDenyRequest', 'Decline Friend');
no.onclick = async () => {
client.notice.refuse_friend(this.user_id);
}
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.user_id);
else
await client.notice.ask_friend(this.user_id);
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);
}
}
}

View File

@ -1,27 +1,27 @@
import AbstractView from "./abstracts/AbstractView.js";
import {client} from "../index.js";
import { client, lang } from "../index.js";
import {Message} from "../api/chat/message.js"
export default class extends AbstractView {
constructor(params) {
super(params, "Search");
super(params, 'SearchWindowTitle');
}
async wait_get_online_users() {
return new Promise((resolve) => {
const checkInterval = setInterval(() => {
//console.log(client.notice.data["online"].length);
if (client.notice.data["online"].length > 0) {
console.log(client.notice.data["online"]);
if (Object.keys(client.notice.data["online"]).length > 0) {
clearInterval(checkInterval);
resolve();
}
}, 100);
}, 1);
});
}
async postInit() {
let logged = await client.isAuthentificate();
let logged = await client.isAuthenticated();
let profiles = await client.profiles.all();
//console.log(client.notice.data);
@ -29,11 +29,13 @@ export default class extends AbstractView {
return console.log("Error");
//await client.notice.getOnlineUser();
await this.wait_get_online_users();
//await this.wait_get_online_users();
client.notice.rewrite_usernames = this.rewrite_usernames;
client.notice.rewrite_invite = this.display_invite;
let search = document.getElementById("input_user");
search.oninput = () => this.display_users(logged, profiles);
if (search != undefined)
search.oninput = () => this.display_users(logged, profiles);
let chat_input = document.getElementById("input_chat");
//chat_input.addEventListener("keydown", this.display_chat_manager)
@ -66,7 +68,12 @@ export default class extends AbstractView {
username.setAttribute('data-link', '');
username.id = `username${user.id}`
username.href = `/profiles/${user.username}`;
username.style.color = client.notice.data["online"].includes(user.id.toString()) ? "green" : "red";
if (logged && user.id == client.me.id)
username.style.color = "green";
else {
let online = client.notice.data["online"][user.id];
username.style.color = online !== undefined ? online : "gray";
}
username.appendChild(document.createTextNode(user.username));
new_user.appendChild(username);
@ -135,8 +142,14 @@ export default class extends AbstractView {
profiles.filter(user => user.username.toLowerCase().startsWith(search) == true).forEach((user) => {
let username = document.getElementById(`username${user.id}`);
if (username !== null)
username.style.color = client.notice.data["online"].includes(user.id.toString()) ? "green" : "red";
if (username !== null) {
if (user.id == client.me.id)
username.style.color = "green";
else {
let online = client.notice.data["online"][user.id];
username.style.color = online !== undefined ? online : "gray";
}
}
});
}
@ -175,13 +188,15 @@ export default class extends AbstractView {
chat_input.maxLength=255;
chat.appendChild(chat_input);
let members_id = client.channels.channel.members_id;
chat_input.onkeydown = async () => {
if (event.keyCode == 13 && client.channels.channel != undefined) {
//let chat_input = document.getElementById("input_chat");
let chat_text = chat_input.value;
let receivers_id = [];
client.channels.channel.members_id.forEach((member_id) => {
members_id.forEach((member_id) => {
if (member_id != client.me.id)
receivers_id.push(profiles.filter(user => user.id == member_id)[0].id);
});
@ -196,7 +211,7 @@ export default class extends AbstractView {
// Scroll to the bottom of messages
messages.scrollTop = messages.scrollHeight;
this.display_invite(chat);
this.display_invite();
}
@ -242,33 +257,86 @@ export default class extends AbstractView {
}
async display_members(chat, profiles) {
let members_id = client.channels.channel.members_id;
let members = document.createElement("h2");
members.id = "members";
let usernames = "";
client.channels.channel.members_id.forEach((member_id) => {
members_id.forEach((member_id) => {
if (member_id != client.me.id) {
if (usernames.length > 0)
usernames += ", ";
usernames += (profiles.filter(user => user.id == member_id)[0].username);
}
});
members.appendChild(document.createTextNode(usernames));
members.textContent = usernames;
chat.appendChild(members);
return members
}
async display_invite(chat, profiles) {
async display_invite() {
let chat = document.getElementById("chat");
if (chat == undefined)
return ;
let members_id = client.channels.channel.members_id;
let others = members_id.filter(id => id !== client.me.id);
// Button to send invite to play
let invite = document.getElementById("invite") || document.createElement("button");
invite.id = "invite";
invite.innerText = "invite";
invite.onclick = async () => {
await client.notice.sendInvite(client.me.id,
client.channels.channel.members_id.filter(id => id !== client.me.id));
};
chat.appendChild(invite);
let yes = document.getElementById("yes") || document.createElement("button");
let no = document.getElementById("no") || document.createElement("button");
let invitedBy = undefined;
for (let x in others) {
if (client.notice.data["invited"].includes(others[x])) {
invitedBy = others[x];
}
}
if (invitedBy == undefined) {
if (yes && no) {
yes.remove();
no.remove();
}
// Button to send invite to play
invite.id = "invite";
invite.style.background = "orange";
invite.innerText = "invite";
invite.title = "Invite to play a game"
invite.onclick = async () => {
await client.notice.send_invite(others);
};
chat.appendChild(invite);
}
else {
if (invite)
invite.remove()
yes.id = "yes";
yes.style.background = "green";
yes.title = "Accept to play a game"
yes.onclick = async () => {
await client.notice.accept_invite(invitedBy);
};
no.id = "no";
no.style.background = "red";
no.title = "Refuse to play a game"
no.onclick = async () => {
await client.notice.refuse_invite(invitedBy);
};
chat.appendChild(yes);
chat.appendChild(no);
}
}

View File

@ -1,12 +1,13 @@
import { client, navigateTo } from "../index.js";
import { clear, fill_errors } from "../utils/formUtils.js";
import AbstractAuthentificateView from "./abstracts/AbstractAuthentifiedView.js";
import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthentificateView
export default class extends AbstractAuthenticatedView
{
constructor(params)
{
super(params, "Me");
super(params, "Settings");
this.PROFILE_PICTURE_MAX_SIZE = 2 * 1024 * 1024; // 2MB
}
async postInit()
@ -24,7 +25,7 @@ export default class extends AbstractAuthentificateView
document.getElementById("avatar").remove();
let avatar = document.createElement("img");
avatar.id = "avatar";
avatar.src = profile.avatar_url;
avatar.src = profile.avatar_url + '?t=' +new Date().getTime();
document.getElementsByClassName("avatar")[0].appendChild(avatar);
}
}
@ -35,7 +36,7 @@ export default class extends AbstractAuthentificateView
let response_data = await client.account.delete(current_password);
console.log(await client.isAuthentificate())
console.log(await client.isAuthenticated())
if (response_data === null || response_data === "user deleted")
{
navigateTo("/login");
@ -78,18 +79,24 @@ export default class extends AbstractAuthentificateView
if (avatar.files[0] !== undefined)
{
if (avatar.files[0].size > this.PROFILE_PICTURE_MAX_SIZE) {
document.getElementById("save-profile").classList.add('text-danger');
document.getElementById("save-profile").innerHTML = "Image too large :/";
return;
}
let form_data = new FormData();
form_data.append("file", avatar.files[0]);
form_data.append("avatar", avatar.files[0]);
await client.me.change_avatar(form_data);
this.display_avatar();
}
document.getElementById("save-profile").classList.remove('text-danger');
document.getElementById("save-profile").innerHTML = "Saved";
}
async getHtml()
{
return /* HTML */ `
<link rel="stylesheet" href="/static/css/me.css">
<link rel="stylesheet" href="/static/css/settings.css">
<h1>ME</h1>
<div id="main">
<div class="avatar">

View File

@ -2,13 +2,13 @@ import { client, navigateTo } from "../../index.js";
import AbstractRedirectView from "./AbstractRedirectView.js";
export default class extends AbstractRedirectView{
constructor(params, title) {
super(params, title, "/login");
constructor(params, titleKey, uri = "/login") {
super(params, titleKey, uri);
}
async redirect()
{
if (await client.isAuthentificate() === false)
if (await client.isAuthenticated() === false)
{
navigateTo(this.redirect_url);
return 1;

View File

@ -2,13 +2,13 @@ import { client, navigateTo } from "../../index.js";
import AbstractRedirectView from "./AbstractRedirectView.js";
export default class extends AbstractRedirectView{
constructor(params, title, url) {
super(params, title, url);
constructor(params, titleKey, uri = "/home") {
super(params, titleKey, uri);
}
async redirect()
{
if (await client.isAuthentificate() === false)
if (await client.isAuthenticated() === false)
return 0;
navigateTo(this.redirect_url);
return 1;

View File

@ -2,14 +2,14 @@ import { navigateTo } from "../../index.js";
import AbstractView from "./AbstractView.js";
export default class extends AbstractView{
constructor(params, title, url)
constructor(params, titleKey, uri)
{
super(params, title);
this.redirect_url = url;
super(params, titleKey);
this.redirect_url = uri;
}
async redirect()
{
navigateTo(url);
navigateTo(this.redirect_url);
}
}

View File

@ -1,7 +1,9 @@
import {lang} from '../../index.js'
export default class {
constructor(params, title) {
constructor(params, titleKey) {
this.params = params;
this.title = title;
this.titleKey = titleKey;
}
async postInit() {
@ -11,7 +13,7 @@ export default class {
}
setTitle() {
document.title = this.title;
document.title = lang.get(this.titleKey, 'Bozo Pong');
}
async getHtml() {

View File

@ -0,0 +1,177 @@
import { client, lang, navigateTo } from "../../index.js";
import { clear, fill_errors } from "../../utils/formUtils.js";
import AbstractNonAuthenticatedView from "../abstracts/AbstractNonAuthenticatedView.js";
export default class extends AbstractNonAuthenticatedView
{
constructor(params, lastUrlBeforeLogin = '/home')
{
super(params, 'loginWindowTitle', lastUrlBeforeLogin);
this.redirect_url = lastUrlBeforeLogin;
this.current_mode = undefined
}
async leavePage()
{
this.current_mode = undefined;
}
/**
* @returns {Promise}
*/
async postInit()
{
let element = document.getElementById("toggle-register-login");
element.onclick = this.toggle_register_login.bind(this);
let new_mode = location.pathname.slice(1);
this.update_mode(new_mode);
document.getElementById("button").onclick = this.authentication.bind(this);
let username_input = document.getElementById('username-input'),
password_input = document.getElementById('password-input');
[username_input, password_input].forEach(input => {
input.addEventListener('keydown', async ev => {
if (ev.key === 'Enter')
await this.authentication.bind(this)()
});
});
username_input.focus();
}
/**
* Check if field is normal
* @param username {String}
* @param password {String}
* @returns {Boolean}
*/
basic_verif(username, password)
{
if (username === '')
document.getElementById('username').innerHTML = lang.get('errorEmptyField', 'This field may not be blank.');
if (password === '')
document.getElementById('password').innerHTML = lang.get('errorEmptyField', 'This field may not be blank.');
if (username === '' || password === '')
return false;
return true
}
/**
* @returns { undefined }
*/
toggle_register_login(event)
{
event.preventDefault();
let new_mode = this.current_mode === "register" ? "login" : "register";
this.update_mode(new_mode);
}
/**
* @param {String} new_mode
*/
update_mode(new_mode)
{
if (new_mode === this.current_mode)
return;
this.current_mode = new_mode;
let title = document.getElementById("title"),
username_label = document.getElementById("username-label"),
password_label = document.getElementById("password-label"),
toggle_register_login = document.getElementById("toggle-register-login"),
toggle_register_login_label = document.getElementById("toggle-register-login-label"),
button = document.getElementById("button")
;
let title_text = this.current_mode === "register" ? "registerFormTitle" : "loginFormTitle";
title.innerText = lang.get(title_text, "ERROR LANG");
let username_label_text = this.current_mode === "register" ? "registerFormUsername" : "loginFormUsername";
username_label.innerText = lang.get(username_label_text, "ERROR LANG");
let password_label_text = this.current_mode === "register" ? "registerFormPassword" : "loginFormPassword";
password_label.innerText = lang.get(password_label_text, "ERROR LANG");
let toggle_register_login_label_text = this.current_mode === "register" ? "registerAlreadyAccount" : "loginNoAccount";
toggle_register_login_label.innerText = lang.get(toggle_register_login_label_text, "ERROR LANG");;
let toggle_register_login_text = this.current_mode === "register" ? "registerLogin" : "loginRegister";
toggle_register_login.innerText = lang.get(toggle_register_login_text, "ERROR LANG");
let button_text = this.current_mode === "register" ? "registerFormButton" : "loginFormButton";
button.innerText = lang.get(button_text, "ERROR LANG");
this.titleKey = this.current_mode === 'register' ? 'registerWindowTitle' : 'loginWindowTitle';
this.setTitle();
}
/**
* @returns {Promise}
*/
async authentication()
{
let username = document.getElementById("username-input").value,
password = document.getElementById("password-input").value;
if (!this.basic_verif())
return;
let response;
if (this.current_mode === "register")
response = await client.account.create(username, password)
else
response = await client.login(username, password);
if (response.status === 200 || response.status === 201)
{
navigateTo(this.redirect_url);
return;
}
let response_data = await response.json()
console.log(response_data);
clear("innerHTML", ["username", "password", 'login']);
fill_errors(response_data, "innerHTML");
}
async getHtml()
{
return /* HTML */ `
<div class='container-fluid'>
<form 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">Loading...</h4>
<div class='form-floating mb-2'>
<input type='text' class='form-control' id='username-input' placeholder='Username'>
<label for='usernameInput' id='username-label'>Loading...</label>
<span class='text-danger' id='username'></span>
</div>
<div class='form-floating'>
<input type='password' class='form-control' id='password-input' placeholder='Password'>
<label for='password-input' id='password-label'>Loading...</label>
<span class='text-danger' id='password'></span>
</div>
<div class='d-flex'>
<button type='button' class='btn btn-primary mt-3 mb-2' id='button'>Loading...</button>
<span class='text-danger my-auto mx-2' id='login'></span>
<div class='ms-auto mt-auto flex-row d-flex gap-2' id="toggle">
<p id='toggle-register-login-label'>Loading...</p>
<a id="toggle-register-login" href='#'>Loading...</a>
</div>
</div>
</form>
</div>
`;
}
}

View File

@ -1,79 +0,0 @@
import { client, navigateTo } from "../../index.js";
import { clear, fill_errors } from "../../utils/formUtils.js";
import AbstractNonAuthentifiedView from "../abstracts/AbstractNonAuthentified.js";
async function login(redirectTo = '/home')
{
clear('innerHTML', ['username', 'password', 'login']);
let username = document.getElementById('usernameInput').value;
let password = document.getElementById('passwordInput').value;
if (username === '') {
document.getElementById('username').innerHTML = 'This field may not be blank.';
}
if (password === '') {
document.getElementById('password').innerHTML = 'This field may not be blank.';
}
if (username === '' || password === '')
return;
let response = await client.login(username, password);
if (response.status == 200) {
await client.notice.disconnect();
await client.notice.connect();
navigateTo(redirectTo);
} else {
let error = await response.json();
fill_errors(error, "innerHTML");
}
}
export default class extends AbstractNonAuthentifiedView {
constructor(params, lastUrlBeforeLogin = '/home') {
super(params, "Login", lastUrlBeforeLogin);
this.redirectTo = lastUrlBeforeLogin;
}
async postInit()
{
let usernameField = document.getElementById('usernameInput');
usernameField.addEventListener('keydown', ev => {
if (ev.key === 'Enter')
login(this.redirectTo);
});
usernameField.focus();
let passwordField = document.getElementById('passwordInput');
passwordField.addEventListener('keydown', ev => {
if (ev.key === 'Enter')
login(this.redirectTo);
});
document.getElementById('loginButton').onclick = _ => login(this.redirectTo);
}
async getHtml() {
return `
<div class='container-fluid'>
<form 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'>Login</h4>
<div class='form-floating mb-2'>
<input type='text' class='form-control' id='usernameInput' placeholder='Username'>
<label for='usernameInput'>Username</label>
<span class='text-danger' id='username'></span>
</div>
<div class='form-floating'>
<input type='password' class='form-control' id='passwordInput' placeholder='Password'>
<label for='passwordInput'>Password</label>
<span class='text-danger' id='password'></span>
</div>
<div class='d-flex'>
<button type='button' class='btn btn-primary mt-3 mb-2' id='loginButton'>Login</button>
<span class='text-danger my-auto mx-2' id='login'></span>
<p class='ms-auto mt-auto'>No account yet? <a href='/register' data-link>Register</a></p>
</div>
</form>
</div>
`;
}
}

View File

@ -1,10 +1,10 @@
import { client, navigateTo } from "../../index.js";
import AbstractAuthentifiedView from "../abstracts/AbstractAuthentifiedView.js";
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthentifiedView
export default class extends AbstractAuthenticatedView
{
constructor(params, lastPageUrl = '/login') {
super(params, "Logout");
super(params, 'logoutWindowTitle', lastPageUrl);
this.lastPageUrl = lastPageUrl;
}

View File

@ -1,77 +0,0 @@
import { client, navigateTo } from "../../index.js";
import { clear, fill_errors } from "../../utils/formUtils.js";
import AbstractNonAuthentifiedView from "../abstracts/AbstractNonAuthentified.js";
async function register(redirectTo = '/home')
{
let username = document.getElementById("usernameInput").value;
let password = document.getElementById("passwordInput").value;
if (username === '' || password === '') {
clear("innerHTML", ["username", "password"]);
if (username === '')
document.getElementById('username').innerHTML = 'This field may not be blank.';
if (password === '')
document.getElementById('password').innerHTML = 'This field may not be blank.';
return;
}
let response_data = await client.account.create(username, password);
if (response_data == null)
{
navigateTo(redirectTo);
return;
}
clear("innerHTML", ["username", "password", 'register']);
fill_errors(response_data, "innerHTML");
}
export default class extends AbstractNonAuthentifiedView {
constructor(params, lastUrlBeforeLogin = '/home') {
super(params, "Register", lastUrlBeforeLogin);
this.redirectTo = lastUrlBeforeLogin;
}
async postInit()
{
let usernameField = document.getElementById('usernameInput');
usernameField.addEventListener('keydown', ev => {
if (ev.key === 'Enter')
register(this.redirectTo);
});
usernameField.focus();
let passwordField = document.getElementById('passwordInput');
passwordField.addEventListener('keydown', ev => {
if (ev.key === 'Enter')
register(this.redirectTo);
});
document.getElementById("registerButton").onclick = _ => register(this.redirectTo);
}
async getHtml() {
return `
<div class='container-fluid'>
<form 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'>Register</h4>
<div class='form-floating mb-2'>
<input type='text' class='form-control' id='usernameInput' placeholder='Username'>
<label for='usernameInput'>Username</label>
<span class='text-danger' id='username'></span>
</div>
<div class='form-floating'>
<input type='password' class='form-control' id='passwordInput' placeholder='Password'>
<label for='passwordInput'>Password</label>
<span class='text-danger' id='password'></span>
</div>
<div class='d-flex'>
<button type='button' class='btn btn-primary mt-3 mb-2' id='registerButton'>Register</button>
<span class='text-danger my-auto mx-2' id='register'></span>
<p class='ms-auto mt-auto'>Already have an account? <a href='/login' data-link>Login</a></p>
</div>
</form>
</div>
`;
}
}

View File

@ -1,8 +1,8 @@
import {client, navigateTo} from "../../index.js";
import { clear, fill_errors } from "../../utils/formUtils.js";
import AbstractAuthentifiedView from "../abstracts/AbstractAuthentifiedView.js";
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthentifiedView
export default class extends AbstractAuthenticatedView
{
constructor(params)
{

View File

@ -1,7 +1,7 @@
import {client, navigateTo} from "../../index.js";
import AbstractAuthentifiedView from "../abstracts/AbstractAuthentifiedView.js";
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthentifiedView
export default class extends AbstractAuthenticatedView
{
constructor(params)
{

View File

@ -1,7 +1,7 @@
import {client} from "../../index.js";
import AbstractAuthentifiedView from "../abstracts/AbstractAuthentifiedView.js";
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthentifiedView
export default class extends AbstractAuthenticatedView
{
constructor(params)
{