276 lines
8.4 KiB
Vue
276 lines
8.4 KiB
Vue
<template>
|
|
<v-app>
|
|
<v-navigation-drawer :permanent="true">
|
|
<v-list>
|
|
<v-list-item>
|
|
<v-list-item-action class="justify-center">
|
|
<v-row>
|
|
<v-col class="text-center">
|
|
<UploadForm @torrent_added="torrentAdded"/>
|
|
</v-col>
|
|
</v-row>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</v-list>
|
|
<v-divider/>
|
|
<UserStats :stats="user_stats"/>
|
|
<v-divider/>
|
|
<!-- {{dm_status}}-->
|
|
<DM v-if="dm_activated" :dm_files="dm_files" :dm_status="dm_status" :dm_download_location="dm_download_location"/>
|
|
</v-navigation-drawer>
|
|
<v-navigation-drawer v-model="right_drawer" location="right" temporary>
|
|
<Friend v-if="right_drawer" :active_user="display_user.id" @userSelected="userSelectedUpdated"/>
|
|
</v-navigation-drawer>
|
|
<v-app-bar>
|
|
<v-app-bar-title style="max-width: 150px">
|
|
<v-btn variant="plain" href="/">Oxpanel</v-btn>
|
|
</v-app-bar-title>
|
|
<v-row align="center" justify="center" style="max-width: 500px" class="mx-auto">
|
|
<v-col>
|
|
<v-text-field density="comfortable" flat solo-inverted hide-details prepend-inner-icon="mdi-magnify" label="Search" v-model="filters.search" clearable @click:clear="filters.search = ''"/>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<template v-slot:append>
|
|
<v-menu>
|
|
<template v-slot:activator="{ props }">
|
|
<v-btn v-bind="props">Manage</v-btn>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item
|
|
v-if="!$qt.is_active"
|
|
href="https://gitea.devpanel.fr/oxpanel/oxapp25/releases/download/1.0/OxApp_Setup.exe"
|
|
title="Download app"
|
|
/>
|
|
<v-list-item href="/password_change/" title="Change password"/>
|
|
<v-list-item>
|
|
<v-list-item-action>
|
|
<form action="/logout/" method="post">
|
|
<input type="hidden" name="csrfmiddlewaretoken" :value="Cookies.get('csrftoken')">
|
|
<button>Disconnect</button>
|
|
</form>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
<v-btn
|
|
@click="right_drawer = !right_drawer"
|
|
prepend-icon="mdi-account-group"
|
|
:color="display_user.id === user.id ? 'green':'orange'"
|
|
:text="display_user.username"
|
|
/>
|
|
</template>
|
|
|
|
</v-app-bar>
|
|
<v-main>
|
|
<TorrentList :loading="loading_torrents" :torrents="torrents" :delete_disabled="user.id !== display_user.id"/>
|
|
</v-main>
|
|
</v-app>
|
|
</template>
|
|
|
|
<script setup>
|
|
import Cookies from "js-cookie";
|
|
import TorrentList from "@/components/torrent/TorrentList.vue";
|
|
import UploadForm from "@/components/torrent/UploadForm.vue";
|
|
import Friend from "@/components/auth/Friend.vue";
|
|
import UserStats from "@/components/torrent/UserStats.vue";
|
|
import DM from "@/components/torrent/DM.vue";
|
|
</script>
|
|
|
|
<script>
|
|
import Cookies from "js-cookie";
|
|
|
|
export default {
|
|
data(){
|
|
return {
|
|
right_drawer: false,
|
|
user: current_user,
|
|
display_user: {
|
|
id: current_user.id,
|
|
username: "My torrents"
|
|
},
|
|
loading_torrents: false,
|
|
filters: {},
|
|
torrents: [],
|
|
user_stats: {
|
|
torrents_size: 0,
|
|
torrents_len: 0,
|
|
torrent_len_shared: 0,
|
|
torrents_total_len: 0,
|
|
user_max_size: 0,
|
|
user_usage_percent: 0,
|
|
disk_total: 0,
|
|
disk_used: 0,
|
|
disk_free: 0,
|
|
disk_usage_percent: 0,
|
|
},
|
|
filter_timer: null,
|
|
dm_files: {},
|
|
// dm_stats: {},
|
|
dm_status: {},
|
|
dm_download_location: "",
|
|
dm_activated: false
|
|
}
|
|
},
|
|
watch: {
|
|
filters: {
|
|
handler(){
|
|
// console.log(JSON.stringify(this.filters));
|
|
clearTimeout(this.filter_timer);
|
|
this.filter_timer = setTimeout(() => {
|
|
this.fetchTorrents();
|
|
}, 200)
|
|
},
|
|
deep: true
|
|
}
|
|
},
|
|
async mounted(){
|
|
this.$ws.connect("/ws/torrent_event/");
|
|
this.$ws.on("connect", () => {
|
|
this.$ws.send(JSON.stringify({"context": "change_follow_user", "user_id": this.display_user.id}));
|
|
});
|
|
this.$ws.on("json_message", (message) => {
|
|
switch(message.context){
|
|
case "transmission_data_updated":
|
|
this.updateTransmissionData(message.data);
|
|
break;
|
|
case "add_torrent":
|
|
this.fetchTorrent(message.torrent_id);
|
|
this.fetchUserStats();
|
|
break;
|
|
case "remove_torrent":
|
|
this.removeTorrent(message.torrent_id);
|
|
this.fetchUserStats();
|
|
break;
|
|
case "update_torrent":
|
|
this.updateTorrent(message.torrent_id, message.updated_fields)
|
|
break
|
|
}
|
|
})
|
|
await this.fetchTorrents();
|
|
await this.fetchUserStats();
|
|
if(this.$qt.connect()){
|
|
this.$qt.on("ready", () => {
|
|
this.dm_status = this.$qt.getProperty("dm_status");
|
|
this.dm_files = this.$qt.getProperty("dm_files");
|
|
// this.dm_stats = this.$qt.getProperty("dm_stats");
|
|
this.dm_download_location = this.$qt.getProperty("dm_download_location");
|
|
this.dm_activated = true;
|
|
// console.log(JSON.stringify(this.dm_files))
|
|
|
|
this.$qt.on("status_updated", data => {
|
|
this.dm_status = data;
|
|
})
|
|
this.$qt.on("upload_torrent", data => {
|
|
console.log(typeof data);
|
|
this.uploadTorrentB64(data);
|
|
})
|
|
this.$qt.on("files_updated", data => {
|
|
this.dm_files = data;
|
|
})
|
|
this.$qt.on("download_location_updated", data => {
|
|
this.dm_download_location = data;
|
|
})
|
|
})
|
|
}
|
|
},
|
|
methods: {
|
|
async fetchUserStats(){
|
|
let response = await fetch("/api/users/user_stats/");
|
|
this.user_stats = await response.json();
|
|
},
|
|
torrentAdded(torrent){
|
|
if(!(torrent.id in this.torrentsAsObject)){
|
|
this.torrents.unshift(torrent);
|
|
}
|
|
},
|
|
changeDisplayUser(user){
|
|
if(user){
|
|
this.display_user = {
|
|
"username": this.user.id === user.id ? "My torrents": `${user.username} torrents`,
|
|
"id": user.id
|
|
}
|
|
}else{
|
|
|
|
}
|
|
this.display_user = {
|
|
"username": this.user.id === user.id ? "My torrents": `${user.username} torrents`,
|
|
"id": user.id
|
|
}
|
|
this.$ws.send(JSON.stringify({"context": "change_follow_user", "user_id": this.display_user.id}));
|
|
},
|
|
updateTransmissionData(data){
|
|
if(data.hashString in this.torrentsAsObject){
|
|
this.torrentsAsObject[data.hashString].transmission_data = data
|
|
}
|
|
},
|
|
async fetchTorrents(){
|
|
this.loading_torrents = true;
|
|
let filters = {...this.filters, user: this.display_user.id},
|
|
url = `/api/torrents/?${new URLSearchParams(filters)}`;
|
|
|
|
let response = await fetch(url);
|
|
this.torrents = await response.json();
|
|
this.loading_torrents = false;
|
|
},
|
|
async fetchTorrent(torrent_id){
|
|
if(torrent_id in this.torrentsAsObject) return;
|
|
let url = `/api/torrents/${torrent_id}/`;
|
|
let response = await fetch(url);
|
|
if(response.ok){
|
|
let torrent = await response.json();
|
|
if(!(torrent.id in this.torrentsAsObject)) this.torrents.unshift(torrent);
|
|
}else{
|
|
setTimeout(() => this.fetchTorrent(torrent_id), 1000);
|
|
}
|
|
},
|
|
async uploadTorrentB64(b64_torrent){
|
|
let form = new FormData();
|
|
form.append("file", b64_torrent);
|
|
form.append("file_mode", "base64");
|
|
let response = await fetch("/api/torrents/", {
|
|
method: "POST",
|
|
headers: {
|
|
"X-CSRFToken": Cookies.get('csrftoken')
|
|
},
|
|
body: form
|
|
})
|
|
},
|
|
async updateTorrent(torrent_id, updated_fields){
|
|
if(torrent_id in this.torrentsAsObject){
|
|
for(let key in updated_fields){
|
|
this.torrentsAsObject[torrent_id][key] = updated_fields[key];
|
|
}
|
|
}
|
|
},
|
|
async removeTorrent(torrent_id){
|
|
if(!(torrent_id in this.torrentsAsObject)) return;
|
|
for(let i = 0; i < this.torrents.length; i++){
|
|
if(this.torrents[i].id === torrent_id){
|
|
this.torrents.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
async userSelectedUpdated(user){
|
|
await this.changeDisplayUser(user ? user: this.user);
|
|
await this.fetchTorrents();
|
|
|
|
this.right_drawer = false
|
|
},
|
|
},
|
|
computed: {
|
|
torrentsAsObject(){
|
|
let r = {};
|
|
this.torrents.forEach(torrent => {
|
|
r[torrent.id] = torrent;
|
|
});
|
|
return r;
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
|
|
</style> |