This commit is contained in:
2025-03-13 22:08:06 +01:00
commit bab5571428
93 changed files with 4323 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
<template>
<Base>
<v-card class="elevation-12">
<v-toolbar color="primary" dark :flat="true">
<v-toolbar-title>Login form</v-toolbar-title>
<v-spacer/>
</v-toolbar>
<v-card-text class="red--text">
{{error_message}}
</v-card-text>
<v-card-text>
<!-- <v-form @submit.prevent="checkForm" id="check-login-form">-->
<v-form id="check-login-form" method="post" action="/user/login/">
<input type="hidden" :value="Cookies.get('csrftoken')" name="csrfmiddlewaretoken">
<v-text-field id="username" v-model="username" label="Username" name="username" prepend-icon="mdi-account" type="text"/>
<v-text-field id="password" v-model="password" label="Password" name="password" prepend-icon="mdi-lock" type="password"/>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="warning" href="/password_reset/" target="_blank" variant="plain">Password lost</v-btn>
<v-spacer/>
<v-btn type="submit" color="primary" form="check-login-form" variant="elevated" class="text-overline">Login</v-btn>
</v-card-actions>
</v-card>
</Base>
</template>
<script setup>
import Cookies from "js-cookie";
import Base from "./Base.vue";
</script>
<script>
export default {
data(){
return {
error_message: "",
username: "",
password: ""
}
},
mounted() {
if(form_error){
this.error_message = "Bad login/password";
console.log(JSON.stringify(form_error));
}
}
}
</script>

View File

@@ -0,0 +1,13 @@
<template>
<v-app id="inspire">
<v-main>
<v-container class="fill-height" :fluid="true">
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<slot></slot>
</v-col>
</v-row>
</v-container>
</v-main>
</v-app>
</template>

View File

@@ -0,0 +1,66 @@
<template>
<v-list>
<v-list-item>
<v-list-item-action class="justify-center">
<FriendManager :friends="friends" @friends-updated="fetchFriends"/>
</v-list-item-action>
</v-list-item>
<v-divider/>
<v-list-item
:active="active_user === default_user_id"
@click="$emit('userSelected')"
>
<template v-slot:title>
My torrents
</template>
</v-list-item>
<v-list-item
v-for="(friend, i) in friends"
:key="i"
:active="active_user === friend.id"
@click="$emit('userSelected', friend)"
>
<template v-slot:title>
{{friend.username}}
</template>
<template v-slot:subtitle>
{{friend.count_torrent}} torrent{{friend.count_torrent !== 1 ? 's':''}}
</template>
</v-list-item>
</v-list>
</template>
<script setup>
import FriendManager from "./FriendManager.vue";
</script>
<script>
export default {
emits: ["userSelected"],
props: {
active_user: {
type: Number,
required: false
}
},
data(){
return {
friends: [],
default_user_id: current_user.id
}
},
async mounted(){
await this.fetchFriends();
},
methods: {
async fetchFriends(){
let filters = {
"only_friends": true
}
let response = await fetch(`/api/users/?${new URLSearchParams(filters)}`);
this.friends = await response.json();
},
}
}
</script>

View File

@@ -0,0 +1,132 @@
<template>
<v-card>
<v-card-title class="text-center">Manage friends</v-card-title>
<v-card-text
v-if="add_status"
class="text-center justify-center"
:style="{
'background-color': add_status.success ? 'green': 'red',
'padding-top': '13px'
}"
v-text="add_status.message"
/>
<v-card-actions class="justify-center">
<v-text-field @keyup.enter="addFriendRequest" v-model="username_model" prepend-icon="mdi-account-plus"/>
</v-card-actions>
<v-card v-if="friend_requests.length">
<v-card-title>Friends requests</v-card-title>
<v-list>
<v-list-item
v-for="(fr, i) in friend_requests"
:key="i"
:title="fr.username"
>
<template v-slot:append>
<v-row>
<v-col>
<v-btn icon="mdi-check" color="green" @click="acceptFriendRequest(i)"/>
</v-col>
<v-col>
<v-btn icon="mdi-cancel" color="red" @click="removeFriendRequest(i)"/>
</v-col>
</v-row>
</template>
</v-list-item>
</v-list>
</v-card>
<v-divider/>
<v-card v-if="friends.length">
<v-card-title>Friends</v-card-title>
<v-list>
<v-list-item
v-for="(user, i) in friends"
:key="i"
prepend-icon="mdi-account"
:title="user.username"
>
<template v-slot:append>
<v-btn icon="mdi-minus" color="red" variant="plain" @click="removeFriend(i)"/>
</template>
</v-list-item>
</v-list>
</v-card>
</v-card>
</template>
<script>
import Cookies from "js-cookie";
let initial_add_status = {
message: "",
success: null
}
export default {
emits: ["friendsUpdated"],
props: {
friends: {
type: Array,
required: true
}
},
data(){
return {
enabled: false,
username_model: "",
friend_requests: [],
add_status: null
}
},
mounted() {
this.fetchFriendRequests();
},
methods: {
// friend request related
async fetchFriendRequests(){
let response = await fetch("/api/friend_requests/");
this.friend_requests = await response.json()
},
async addFriendRequest(username=null){
if(username === null || typeof username !== "string"){
username = this.username_model
}
let response = await fetch(`/api/users/${username}/add_friend_request/`);
this.add_status = await response.json();
setTimeout(() => {
this.add_status = null;
}, 3000)
this.username_model = "";
await this.fetchFriendRequests();
this.$emit("friendsUpdated");
},
async acceptFriendRequest(i){
let friend_request = this.friend_requests[i];
await this.addFriendRequest(friend_request.username);
this.friend_requests.splice(i, 1);
this.$emit("friendsUpdated");
},
async removeFriendRequest(i){
let friend_request = this.friend_requests[i];
let response = await fetch(`/api/friend_requests/${friend_request.id}/`,
{
method: "DELETE",
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
},
}
);
if(response.ok) this.friend_requests.splice(i, 1);
// todo : check success
},
//friends related
async removeFriend(i){
let user = this.friends[i];
let response = await fetch(`/api/users/${user.id}/remove_friend/`);
let json = await response.json();
if(json.success) this.friends.splice(i, 1);
this.$emit("friendsUpdated");
},
}
}
</script>

View File

@@ -0,0 +1,32 @@
<template>
<v-dialog v-model="enabled" max-width="500">
<template v-slot:activator="{props}">
<v-btn color="blue" prepend-icon="mdi-account-group" text="Manage friends" v-bind="props"/>
</template>
<FriendForm :friends="friends" @friends-updated="$emit('friendsUpdated')"/>
</v-dialog>
</template>
<script setup>
import FriendForm from "./FriendForm.vue";
</script>
<script>
export default {
emits: ["friendsUpdated"],
props: {
friends: {
type: Array,
required: true
}
},
data(){
return {
enabled: false
}
},
methods: {
}
}
</script>