Compare commits
	
		
			17 Commits
		
	
	
		
			609b045315
			...
			651fbbd67f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 651fbbd67f | |||
| 1961047703 | |||
| 929c1fdeb3 | |||
| 980a66fb47 | |||
| ceed7c2c4a | |||
| 6a537a9b68 | |||
| 26a9152756 | |||
| f32d38287a | |||
| 51354d9922 | |||
| b5d73e59fd | |||
| 86e2528d04 | |||
| 1f41e62a86 | |||
| 51059e6bf3 | |||
| 115ae9357a | |||
| 1b44d5c94f | |||
| 468a3917a9 | |||
| 9be65a2bab | 
@ -24,7 +24,7 @@ pip install -r requirements.txt
 | 
			
		||||
```
 | 
			
		||||
python manage.py makemigrations games
 | 
			
		||||
python manage.py makemigrations profiles
 | 
			
		||||
python manage.py runserver makemigrations chat
 | 
			
		||||
python manage.py makemigrations chat
 | 
			
		||||
python manage.py migrate
 | 
			
		||||
```
 | 
			
		||||
- Start the developpement server
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
body {
 | 
			
		||||
    margin: 20px;
 | 
			
		||||
    margin: 0.5em;
 | 
			
		||||
    font-family: 'Quicksand', sans-serif;
 | 
			
		||||
    font-size: 60px;
 | 
			
		||||
    font-size: 40px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
 | 
			
		||||
@ -1,19 +1,18 @@
 | 
			
		||||
#app .account
 | 
			
		||||
#app #main .account
 | 
			
		||||
{
 | 
			
		||||
	background-color: red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .account, #app .profile
 | 
			
		||||
#app #main
 | 
			
		||||
{
 | 
			
		||||
	width: 60%;
 | 
			
		||||
	display: flex;
 | 
			
		||||
	margin-left: auto;
 | 
			
		||||
	margin-right: auto;
 | 
			
		||||
	flex-direction: column;
 | 
			
		||||
	flex-wrap: wrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .profile
 | 
			
		||||
#app #main .profile
 | 
			
		||||
{
 | 
			
		||||
	background-color: green;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app #messages {
 | 
			
		||||
	max-height: 50em;
 | 
			
		||||
	max-height: 40em;
 | 
			
		||||
	overflow: scroll;
 | 
			
		||||
	overflow-y: scroll;
 | 
			
		||||
	overflow-x: hidden;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								frontend/static/js/api/MyProfile.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								frontend/static/js/api/MyProfile.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
import { Profile } from "./profile.js";
 | 
			
		||||
 | 
			
		||||
class MyProfile extends Profile
 | 
			
		||||
{
 | 
			
		||||
	async change_avatar(form_data)
 | 
			
		||||
	{
 | 
			
		||||
		let response = await this.client._patch_file(`/api/profiles/me`, form_data);
 | 
			
		||||
		let response_data = await response.json()
 | 
			
		||||
 | 
			
		||||
		return response_data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async init()
 | 
			
		||||
	{
 | 
			
		||||
		super.init("me");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {MyProfile}
 | 
			
		||||
@ -1,7 +1,15 @@
 | 
			
		||||
import { Client } from "./client.js";
 | 
			
		||||
 | 
			
		||||
class Account
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param  {Client} client
 | 
			
		||||
	 */
 | 
			
		||||
	constructor (client)
 | 
			
		||||
	{
 | 
			
		||||
		/**
 | 
			
		||||
		 * @type  {Client} client
 | 
			
		||||
		 */
 | 
			
		||||
		this.client = client;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
@ -28,7 +36,6 @@ class Account
 | 
			
		||||
			this.client._logged = false;
 | 
			
		||||
			return null;			
 | 
			
		||||
		}
 | 
			
		||||
		console.log(response_data)
 | 
			
		||||
		if (response_data == "user deleted")
 | 
			
		||||
			this.client._logged = false;
 | 
			
		||||
		return response_data;
 | 
			
		||||
@ -55,7 +62,7 @@ class Account
 | 
			
		||||
 | 
			
		||||
		if (JSON.stringify(response_data) == JSON.stringify({'detail': 'Authentication credentials were not provided.'}))
 | 
			
		||||
		{
 | 
			
		||||
			this.client._logged = false;
 | 
			
		||||
			this.client._;
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
		return response_data;
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import { Account } from "./account.js";
 | 
			
		||||
import { MatchMaking } from "./matchmaking.js";
 | 
			
		||||
import { Profile } from "./profile.js";
 | 
			
		||||
import { Profiles } from "./profiles.js";
 | 
			
		||||
import { Channels } from './chat/channels.js';
 | 
			
		||||
import { MyProfile } from "./MyProfile.js";
 | 
			
		||||
 | 
			
		||||
function getCookie(name)
 | 
			
		||||
{
 | 
			
		||||
@ -94,15 +94,23 @@ class Client
 | 
			
		||||
        return response;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	async _update_logged(state)
 | 
			
		||||
	{
 | 
			
		||||
		if (!this.logged && state)
 | 
			
		||||
		{
 | 
			
		||||
			this.me = new MyProfile(this);
 | 
			
		||||
			await this.me.init();
 | 
			
		||||
		}
 | 
			
		||||
		this.logged = state;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async login(username, password)
 | 
			
		||||
	{
 | 
			
		||||
		let response = await this._post("/api/accounts/login", {username: username, password: password})
 | 
			
		||||
		let data = await response.json();
 | 
			
		||||
		if (data.id != undefined)
 | 
			
		||||
		{
 | 
			
		||||
			this.me = new Profile(this)
 | 
			
		||||
			await this.me.init(data.id)
 | 
			
		||||
			this.logged = true;
 | 
			
		||||
			await this._update_logged(true);
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
		return data;
 | 
			
		||||
@ -111,7 +119,7 @@ class Client
 | 
			
		||||
	async logout()
 | 
			
		||||
	{
 | 
			
		||||
		await this._get("/api/accounts/logout");
 | 
			
		||||
		this.logged = false;
 | 
			
		||||
		await this._update_logged(false);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async _test_logged()
 | 
			
		||||
@ -120,10 +128,7 @@ class Client
 | 
			
		||||
		let data = await response.json();
 | 
			
		||||
 | 
			
		||||
		if (data.id !== undefined)
 | 
			
		||||
		{
 | 
			
		||||
			this.me = new Profile(this)
 | 
			
		||||
			await this.me.init(data.id)
 | 
			
		||||
		}
 | 
			
		||||
			await this._update_logged(true);
 | 
			
		||||
		return data.id !== undefined;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
import { client, navigateTo } from "../index.js"
 | 
			
		||||
import { Client } from "./client.js";
 | 
			
		||||
 | 
			
		||||
class MatchMaking
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param  {client} client
 | 
			
		||||
	 * @param  {Client} client
 | 
			
		||||
	 */
 | 
			
		||||
	constructor(client)
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,15 @@
 | 
			
		||||
import { Client } from "./client.js";
 | 
			
		||||
 | 
			
		||||
class Profile
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param  {Client} client
 | 
			
		||||
	 */
 | 
			
		||||
	constructor (client, username = undefined, avatar_url = undefined, user_id = undefined)
 | 
			
		||||
	{
 | 
			
		||||
		/**
 | 
			
		||||
		 * @type  {Client} client
 | 
			
		||||
		 */
 | 
			
		||||
		this.client = client;
 | 
			
		||||
		this.username = username;
 | 
			
		||||
		this.avatar_url = avatar_url
 | 
			
		||||
@ -13,23 +21,10 @@ class Profile
 | 
			
		||||
		let response = await this.client._get(`/api/profiles/${user_id}`);
 | 
			
		||||
		let response_data = await response.json();
 | 
			
		||||
 | 
			
		||||
		this.user_id = user_id;
 | 
			
		||||
		this.user_id = response.user_id;
 | 
			
		||||
		this.username = response_data.username;
 | 
			
		||||
		this.avatar_url = response_data.avatar_url;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async change_avatar(form_data)
 | 
			
		||||
	{
 | 
			
		||||
		let response = await this.client._patch_file(`/api/profiles/${this.user_id}`, form_data);
 | 
			
		||||
		let response_data = await response.json()
 | 
			
		||||
 | 
			
		||||
		return response_data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async setData (data)
 | 
			
		||||
	{
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {Profile}
 | 
			
		||||
@ -2,8 +2,14 @@ import { Profile } from "./profile.js";
 | 
			
		||||
 | 
			
		||||
class Profiles
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param  {Client} client
 | 
			
		||||
	 */
 | 
			
		||||
	constructor (client)
 | 
			
		||||
	{
 | 
			
		||||
		/**
 | 
			
		||||
		 * @type {Client} client
 | 
			
		||||
		 */
 | 
			
		||||
		this.client = client
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -79,6 +79,7 @@ const router = async (uri) => {
 | 
			
		||||
 | 
			
		||||
	lastView = view;
 | 
			
		||||
 | 
			
		||||
    await client.isAuthentificate();
 | 
			
		||||
    let content = await view.getHtml();
 | 
			
		||||
    if (content == null)
 | 
			
		||||
        return 1;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								frontend/static/js/utils/formUtils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								frontend/static/js/utils/formUtils.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
function clear(property_name, elements_id)
 | 
			
		||||
{
 | 
			
		||||
	elements_id.forEach(element_id => {
 | 
			
		||||
		let element = document.getElementById(element_id)
 | 
			
		||||
		element[property_name] = ""
 | 
			
		||||
	});	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fill_errors(errors, property_name)
 | 
			
		||||
{
 | 
			
		||||
	Object.keys(errors).forEach(error_field =>
 | 
			
		||||
	{
 | 
			
		||||
		let element = document.getElementById(error_field);
 | 
			
		||||
		element[property_name] = errors[error_field];
 | 
			
		||||
	});	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {fill_errors, clear}
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
import { client, navigateTo } from "../index.js";
 | 
			
		||||
import { clear, fill_errors } from "../utils/formUtils.js";
 | 
			
		||||
import AbstractAuthentificateView from "./AbstractAuthentifiedView.js";
 | 
			
		||||
 | 
			
		||||
export default class extends AbstractAuthentificateView
 | 
			
		||||
@ -10,63 +11,39 @@ export default class extends AbstractAuthentificateView
 | 
			
		||||
 | 
			
		||||
    async postInit()
 | 
			
		||||
    {
 | 
			
		||||
        if (this.fill() === null)
 | 
			
		||||
            return;
 | 
			
		||||
        document.getElementById("save-account-button").onclick = this.acccount_save;
 | 
			
		||||
        document.getElementById("delete-account-button").onclick = this.account_delete_accounts;
 | 
			
		||||
        document.getElementById("save-account-button").onclick = this.save_account;
 | 
			
		||||
        document.getElementById("delete-account-button").onclick = this.delete_account;
 | 
			
		||||
        document.getElementById("save-profile-button").onclick = this.save_profile;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fill()
 | 
			
		||||
    async delete_account()
 | 
			
		||||
    {
 | 
			
		||||
        let data = await client.account.get();
 | 
			
		||||
    
 | 
			
		||||
        if (data === null)
 | 
			
		||||
        {
 | 
			
		||||
            navigateTo("/login")
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        document.getElementById("username").value = data.username;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async delete_accounts()
 | 
			
		||||
    {
 | 
			
		||||
        let current_password = document.getElementById("current_password").value;
 | 
			
		||||
        let current_password = document.getElementById("current_password-input").value;
 | 
			
		||||
        
 | 
			
		||||
        let response_data = await client.account.delete(current_password);
 | 
			
		||||
 | 
			
		||||
        if (response_data === null)
 | 
			
		||||
        console.log(await client.isAuthentificate())
 | 
			
		||||
        if (response_data === null || response_data === "user deleted")
 | 
			
		||||
        {
 | 
			
		||||
            navigateTo("/login");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ["delete", "current_password"].forEach(error_field => {
 | 
			
		||||
            let error_display = document.getElementById(`error_${error_field}`);
 | 
			
		||||
            if (error_display != null)
 | 
			
		||||
                error_display.innerHTML = "";
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (response_data === "user deleted")
 | 
			
		||||
        {
 | 
			
		||||
            document.getElementById(`error_delete`).innerHTML = "OK";
 | 
			
		||||
            navigateTo("/login")
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        document.getElementById("error_current_password").innerHTML = response_data["password"]
 | 
			
		||||
        clear("innerHTML", ["current_password-input"])
 | 
			
		||||
        fill_errors({"current_password-input": response_data["password"]}, "innerHTML")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async save()
 | 
			
		||||
    async save_account()
 | 
			
		||||
    {
 | 
			
		||||
        let username = document.getElementById("username").value;
 | 
			
		||||
        let new_password = document.getElementById("new_password").value;
 | 
			
		||||
        let current_password = document.getElementById("current_password").value;
 | 
			
		||||
        let username = document.getElementById("username-input").value;
 | 
			
		||||
        let new_password = document.getElementById("new_password-input").value;
 | 
			
		||||
        let current_password = document.getElementById("current_password-input").value;
 | 
			
		||||
    
 | 
			
		||||
        let data = {};
 | 
			
		||||
    
 | 
			
		||||
        data.username = username;
 | 
			
		||||
        if (new_password.length != 0)
 | 
			
		||||
            data.new_password = new_password;
 | 
			
		||||
 | 
			
		||||
        let response_data = await client.account.update(data, current_password);
 | 
			
		||||
 | 
			
		||||
        if (response_data === null)
 | 
			
		||||
@ -74,58 +51,55 @@ export default class extends AbstractAuthentificateView
 | 
			
		||||
            navigateTo("/login");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        else if (response_data === "data has been alterate")
 | 
			
		||||
        {
 | 
			
		||||
            navigateTo("/me");
 | 
			
		||||
            return; 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (response_data === "data has been alterate")
 | 
			
		||||
            response_data = {"save-account": "saved"}
 | 
			
		||||
 | 
			
		||||
        clear("innerHTML", ["username", "new_password", "current_password", "save-account", "delete-account"])
 | 
			
		||||
        fill_errors(response_data, "innerHTML")
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
        ["username", "new_password", "current_password"].forEach(error_field => {
 | 
			
		||||
            let error_display = document.getElementById(`error_${error_field}`);
 | 
			
		||||
            if (error_display != null)
 | 
			
		||||
                error_display.innerHTML = "";
 | 
			
		||||
        });
 | 
			
		||||
    
 | 
			
		||||
        Object.keys(response_data).forEach(error_field => {
 | 
			
		||||
            let error_display = document.getElementById(`error_${error_field}`);
 | 
			
		||||
            if (error_display != null)
 | 
			
		||||
                error_display.innerHTML = response_data[error_field];
 | 
			
		||||
        });
 | 
			
		||||
        let avatar = document.getElementById("avatar");
 | 
			
		||||
    async save_profile()
 | 
			
		||||
    {
 | 
			
		||||
        let avatar = document.getElementById("avatar-input");
 | 
			
		||||
 | 
			
		||||
        if (avatar.files[0] !== undefined)
 | 
			
		||||
        {
 | 
			
		||||
            let form_data = new FormData();
 | 
			
		||||
            form_data.append("file", avatar.files[0]);
 | 
			
		||||
            await client.me.change_avatar(form_data)
 | 
			
		||||
            await client.me.change_avatar(form_data);
 | 
			
		||||
        }
 | 
			
		||||
        document.getElementById("save-profile").innerHTML = "Saved";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    async getHtml()
 | 
			
		||||
    {
 | 
			
		||||
        return `
 | 
			
		||||
            <link rel="stylesheet" href="static/css/me.css">
 | 
			
		||||
            <link rel="stylesheet" href="/static/css/me.css">
 | 
			
		||||
			<h1>ME</h1>
 | 
			
		||||
            <div class="account">
 | 
			
		||||
                <h3>Account</h3>
 | 
			
		||||
                <input type="text" placeholder="username" id="username">
 | 
			
		||||
                <span id="error_username"></span>
 | 
			
		||||
                <input type=password placeholder="new password" id="new_password">
 | 
			
		||||
                <span id="error_new_password"></span>
 | 
			
		||||
                <input type=password placeholder="current password" id="current_password">
 | 
			
		||||
                <span id="error_current_password"></span>
 | 
			
		||||
                <input type="button" value="Save Credentials" id="save-account-button">
 | 
			
		||||
                <span id="error_save"></span>
 | 
			
		||||
                <input type="button" value="Delete Account" id="delete-account-button">
 | 
			
		||||
                <span id="error_delete"></span>
 | 
			
		||||
            <div id="main">
 | 
			
		||||
                <div class="account">
 | 
			
		||||
                    <h3>Account</h3>
 | 
			
		||||
                    <input type="text" placeholder="username" id="username-input" text=${client.me.username}>
 | 
			
		||||
                    <span id="username"></span>
 | 
			
		||||
                    <input type=password placeholder="new_password" id="new_password-input">
 | 
			
		||||
                    <span id="new_password"></span>
 | 
			
		||||
                    <input type=password placeholder="current_password" id="current_password-input">
 | 
			
		||||
                    <span id="current_password"></span>
 | 
			
		||||
 | 
			
		||||
                    <input type="button" value="Save Credentials" id="save-account-button">
 | 
			
		||||
                    <span id="save-account"></span>
 | 
			
		||||
                    <input type="button" value="Delete Account" id="delete-account-button">
 | 
			
		||||
                    <span id="delete-account"></span>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="profile">
 | 
			
		||||
                    <h3>Profile</h3>
 | 
			
		||||
                    <input type="file" id="avatar-input" accept="image/png, image/jpeg">
 | 
			
		||||
                    <input type="button" value="Save profile" id="save-profile-button">
 | 
			
		||||
                    <span id="save-profile"></span>
 | 
			
		||||
                </div>
 | 
			
		||||
                <a href="/logout" class="nav__link" data-link>Logout</a>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="profile">
 | 
			
		||||
                <h3>Profile</h3>
 | 
			
		||||
                <input type="file" id="avatar" accept="image/png, image/jpeg">
 | 
			
		||||
                <input type="button" value="Save profile" id="save-profile-button">
 | 
			
		||||
                <span id="error_save"></span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <a href="/logout" class="nav__link" data-link>Logout</a>
 | 
			
		||||
        `;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -52,6 +52,7 @@ export default class extends AbstractView {
 | 
			
		||||
			// chat
 | 
			
		||||
			if (logged && client.me.user_id != user.user_id) {
 | 
			
		||||
				let add_chat = document.createElement("a");
 | 
			
		||||
				add_chat.href = "";
 | 
			
		||||
				add_chat.id = "add_chat_off";
 | 
			
		||||
				add_chat.onclick = async () => {
 | 
			
		||||
					if (client.channel != undefined) {
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,11 @@
 | 
			
		||||
import { client, navigateTo } from "../../index.js";
 | 
			
		||||
import { clear, fill_errors } from "../../utils/formUtils.js";
 | 
			
		||||
import AbstractNonAuthentifiedView from "../AbstractNonAuthentified.js";
 | 
			
		||||
 | 
			
		||||
async function login()
 | 
			
		||||
{
 | 
			
		||||
	let username = document.getElementById("username").value;
 | 
			
		||||
	let password = document.getElementById("password").value;
 | 
			
		||||
	let username = document.getElementById("username-input").value;
 | 
			
		||||
	let password = document.getElementById("password-input").value;
 | 
			
		||||
	
 | 
			
		||||
	let response_data = await client.login(username, password);
 | 
			
		||||
 | 
			
		||||
@ -14,17 +15,8 @@ async function login()
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	["username", "user", "password"].forEach(error_field => {
 | 
			
		||||
		let error_display = document.getElementById(`error_${error_field}`);
 | 
			
		||||
		if (error_display != null)
 | 
			
		||||
			error_display.innerHTML = "";
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	Object.keys(response_data).forEach(error_field => {
 | 
			
		||||
		let error_display = document.getElementById(`error_${error_field}`);
 | 
			
		||||
		if (error_display != null)
 | 
			
		||||
			error_display.innerHTML = response_data[error_field];
 | 
			
		||||
	});
 | 
			
		||||
	clear("innerHTML", ["username", "user", "password"]);
 | 
			
		||||
	fill_errors(response_data, "innerHTML");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class extends AbstractNonAuthentifiedView {
 | 
			
		||||
@ -34,20 +26,20 @@ export default class extends AbstractNonAuthentifiedView {
 | 
			
		||||
 | 
			
		||||
	async postInit()
 | 
			
		||||
	{
 | 
			
		||||
		document.getElementById("button").onclick = login;
 | 
			
		||||
		document.getElementById("login-button").onclick = login;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    async getHtml() {
 | 
			
		||||
        return `
 | 
			
		||||
			<div class=form>
 | 
			
		||||
				<label>Login</label>
 | 
			
		||||
				<link rel="stylesheet" href="static/css/accounts/login.css">
 | 
			
		||||
				<input type="text" id="username" placeholder="username">
 | 
			
		||||
				<span id="error_username"></span>
 | 
			
		||||
				<input type="password" id="password" placeholder="password">
 | 
			
		||||
				<span id="error_password"></span>
 | 
			
		||||
				<input type="button" value="login" id="button">
 | 
			
		||||
				<span id="error_user"></span>
 | 
			
		||||
				<link rel="stylesheet" href="/static/css/accounts/login.css">
 | 
			
		||||
				<input type="text" id="username-input" placeholder="username">
 | 
			
		||||
				<span id="username"></span>
 | 
			
		||||
				<input type="password" id="password-input" placeholder="password">
 | 
			
		||||
				<span id="password"></span>
 | 
			
		||||
				<input type="button" value="Login" id="login-button">
 | 
			
		||||
				<span id="user"></span>
 | 
			
		||||
				<a href="/register" class="nav__link" data-link>Register</a>
 | 
			
		||||
			</div>
 | 
			
		||||
        `;
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,11 @@
 | 
			
		||||
import { client, navigateTo } from "../../index.js";
 | 
			
		||||
import { clear, fill_errors } from "../../utils/formUtils.js";
 | 
			
		||||
import AbstractNonAuthentifiedView from "../AbstractNonAuthentified.js";
 | 
			
		||||
 | 
			
		||||
async function register()
 | 
			
		||||
{
 | 
			
		||||
	let username = document.getElementById("username").value;
 | 
			
		||||
	let password = document.getElementById("password").value;
 | 
			
		||||
	let username = document.getElementById("username-input").value;
 | 
			
		||||
	let password = document.getElementById("password-input").value;
 | 
			
		||||
	
 | 
			
		||||
	let response_data = await client.account.create(username, password);
 | 
			
		||||
 | 
			
		||||
@ -14,17 +15,8 @@ async function register()
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	["username", "user", "password"].forEach(error_field => {
 | 
			
		||||
		let error_display = document.getElementById(`error_${error_field}`);
 | 
			
		||||
		if (error_display != null)
 | 
			
		||||
			error_display.innerHTML = "";
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	Object.keys(response_data).forEach(error_field => {
 | 
			
		||||
		let error_display = document.getElementById(`error_${error_field}`);
 | 
			
		||||
		if (error_display != null)
 | 
			
		||||
			error_display.innerHTML = response_data[error_field];
 | 
			
		||||
	});
 | 
			
		||||
	clear("innerHTML", ["username", "user", "password"]);
 | 
			
		||||
	fill_errors(response_data, "innerHTML");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class extends AbstractNonAuthentifiedView {
 | 
			
		||||
@ -34,20 +26,20 @@ export default class extends AbstractNonAuthentifiedView {
 | 
			
		||||
 | 
			
		||||
	async postInit()
 | 
			
		||||
	{
 | 
			
		||||
		document.getElementById("button").onclick = register;
 | 
			
		||||
		document.getElementById("register-button").onclick = register;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    async getHtml() {
 | 
			
		||||
        return `
 | 
			
		||||
			<div class=form>
 | 
			
		||||
				<label>Register</label>
 | 
			
		||||
				<link rel="stylesheet" href="static/css/accounts/register.css">
 | 
			
		||||
				<input type="text" id="username" placeholder="username">
 | 
			
		||||
				<span id="error_username"></span>
 | 
			
		||||
				<input type="password" id="password" placeholder="password">
 | 
			
		||||
				<span id="error_password"></span>
 | 
			
		||||
				<input type="button" value="register" id="button">
 | 
			
		||||
				<span id="error_user"></span>
 | 
			
		||||
				<link rel="stylesheet" href="/static/css/accounts/register.css">
 | 
			
		||||
				<input type="text" id="username-input" placeholder="username">
 | 
			
		||||
				<span id="username"></span>
 | 
			
		||||
				<input type="password" id="password-input" placeholder="password">
 | 
			
		||||
				<span id="password"></span>
 | 
			
		||||
				<input type="button" value="Register" id="register-button">
 | 
			
		||||
				<span id="user"></span>
 | 
			
		||||
				<a href="/login" class="nav__link" data-link>Login</a>
 | 
			
		||||
			</div>
 | 
			
		||||
        `;
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ from django.conf.urls.static import static
 | 
			
		||||
from . import viewsets
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path("<int:pk>", viewsets.ProfileViewSet.as_view({'get': 'retrieve', 'patch': 'partial_update'}), name="profile_page"),
 | 
			
		||||
    path("me", viewsets.MyProfileViewSet.as_view({'patch': 'partial_update', 'get': 'retrieve'}), name="my_profile_page"),
 | 
			
		||||
    path("<int:pk>", viewsets.ProfileViewSet.as_view({'get': 'retrieve'}), name="profile_page"),
 | 
			
		||||
    path("", viewsets.ProfileViewSet.as_view({'get': 'list'}), name="profiles_list"),
 | 
			
		||||
    #path("me", viewsets.ProfileViewSet.as_view(), name="my_profile_page"),
 | 
			
		||||
] + static("/static/avatars/", document_root="./avatars")
 | 
			
		||||
@ -3,6 +3,7 @@ from rest_framework.parsers import MultiPartParser, FormParser
 | 
			
		||||
from rest_framework import permissions, status
 | 
			
		||||
from rest_framework import viewsets
 | 
			
		||||
from rest_framework.response import Response
 | 
			
		||||
from rest_framework.authentication import SessionAuthentication
 | 
			
		||||
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.db.models import QuerySet
 | 
			
		||||
@ -17,7 +18,9 @@ class ProfileViewSet(viewsets.ModelViewSet):
 | 
			
		||||
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
 | 
			
		||||
 | 
			
		||||
    def retrieve(self, request: HttpRequest, pk=None):
 | 
			
		||||
        instance = ProfileModel.objects.get(pk=pk)
 | 
			
		||||
        if (not self.queryset().filter(pk=pk).exists()):
 | 
			
		||||
            return Response({"detail": "Profile not found."}, status=status.HTTP_404_NOT_FOUND)
 | 
			
		||||
        instance = self.queryset().get(pk=pk)
 | 
			
		||||
        instance.avatar_url.name = instance.avatar_url.name[instance.avatar_url.name.find("static") - 1:]
 | 
			
		||||
        return Response(self.serializer_class(instance).data,
 | 
			
		||||
                        status=status.HTTP_200_OK)
 | 
			
		||||
@ -31,14 +34,28 @@ class ProfileViewSet(viewsets.ModelViewSet):
 | 
			
		||||
    def perform_create(self, serializer):
 | 
			
		||||
        serializer.save(user=self.request.user)
 | 
			
		||||
 | 
			
		||||
    def perform_update(self, serializer):
 | 
			
		||||
        query: QuerySet = ProfileModel.objects.filter(pk=self.request.user.pk)
 | 
			
		||||
        if (not query.exists()):
 | 
			
		||||
            return Response("profile not found", status=status.HTTP_400_BAD_REQUEST)
 | 
			
		||||
        profile: ProfileModel = ProfileModel.objects.get(pk=self.request.user.pk)
 | 
			
		||||
class MyProfileViewSet(viewsets.ModelViewSet):
 | 
			
		||||
 | 
			
		||||
    permission_classes = (permissions.IsAuthenticated,)
 | 
			
		||||
    authentication_classes = (SessionAuthentication,)
 | 
			
		||||
    serializer_class = ProfileSerializer
 | 
			
		||||
    queryset = ProfileModel.objects.all
 | 
			
		||||
 | 
			
		||||
    def get_object(self):
 | 
			
		||||
        obj = self.queryset().get(pk=self.request.user.pk)
 | 
			
		||||
        return obj
 | 
			
		||||
 | 
			
		||||
    def perform_update(self, serializer, pk=None):
 | 
			
		||||
        profile: ProfileModel = self.get_object()
 | 
			
		||||
        avatar = self.request.data.get("file", None)
 | 
			
		||||
        if (avatar is not None):
 | 
			
		||||
            if (profile.avatar_url.name != "./profiles/static/avatars/default.avif"):
 | 
			
		||||
                profile.avatar_url.storage.delete(profile.avatar_url.name)
 | 
			
		||||
            profile.avatar_url = avatar
 | 
			
		||||
        profile.save()
 | 
			
		||||
        profile.save()
 | 
			
		||||
    
 | 
			
		||||
    def retrieve(self, request: HttpRequest, pk=None):
 | 
			
		||||
        instance: ProfileModel = self.get_object()
 | 
			
		||||
        instance.avatar_url.name = instance.avatar_url.name[instance.avatar_url.name.find("static") - 1:]
 | 
			
		||||
        return Response(self.serializer_class(instance).data,
 | 
			
		||||
                        status=status.HTTP_200_OK)
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user