init
This commit is contained in:
49
app/frontend/src/components/auth/App.vue
Normal file
49
app/frontend/src/components/auth/App.vue
Normal 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>
|
||||
13
app/frontend/src/components/auth/Base.vue
Normal file
13
app/frontend/src/components/auth/Base.vue
Normal 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>
|
||||
66
app/frontend/src/components/auth/Friend.vue
Normal file
66
app/frontend/src/components/auth/Friend.vue
Normal 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>
|
||||
132
app/frontend/src/components/auth/FriendForm.vue
Normal file
132
app/frontend/src/components/auth/FriendForm.vue
Normal 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>
|
||||
32
app/frontend/src/components/auth/FriendManager.vue
Normal file
32
app/frontend/src/components/auth/FriendManager.vue
Normal 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>
|
||||
Reference in New Issue
Block a user