Compare commits

..

5 Commits

Author SHA1 Message Date
9b9c25806b Fix null to 0 in aggregate 2025-04-20 03:20:34 +02:00
065ac7f250 update debug mode 2025-04-20 03:13:04 +02:00
0a5251ec10 some fix 2025-04-20 03:08:12 +02:00
eb60fc4dd3 fix url to avoid 301 2025-04-20 00:41:21 +02:00
888ed093a1 add title 2025-04-19 23:15:17 +02:00
15 changed files with 37 additions and 17 deletions

View File

@@ -2,6 +2,7 @@ FROM python:3.13-slim
ARG puid=1000 ARG puid=1000
ARG pgid=1000 ARG pgid=1000
ARG debug=false
ENV PYTHONUNBUFFERED=1 \ ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \ PYTHONDONTWRITEBYTECODE=1 \
LANG=C.UTF-8 \ LANG=C.UTF-8 \
@@ -40,8 +41,13 @@ RUN yarn install
WORKDIR /app WORKDIR /app
RUN pip install --upgrade pip RUN pip install --upgrade pip
COPY ./requirements.txt ./requirements.txt COPY requirements*.txt ./
RUN pip install --no-cache-dir -r requirements.txt RUN if [ "$debug" = "true" ] ; then \
pip install --no-cache-dir -r requirements-dev.txt ; \
else \
pip install --no-cache-dir -r requirements-prod.txt ; \
fi
#COPY . . #COPY . .

View File

@@ -59,6 +59,8 @@ INSTALLED_APPS = [
'api', 'api',
'torrent', 'torrent',
] ]
if DEBUG:
INSTALLED_APPS = ["daphne"] + INSTALLED_APPS
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
@@ -139,6 +141,7 @@ USE_TZ = True
STATIC_URL = '/static/' STATIC_URL = '/static/'
STATICFILES_DIRS = [ STATICFILES_DIRS = [
BASE_DIR / "static",
BASE_DIR / "frontend/dist", BASE_DIR / "frontend/dist",
] ]
STATIC_ROOT = BASE_DIR / "static_collected" STATIC_ROOT = BASE_DIR / "static_collected"

View File

@@ -17,6 +17,7 @@ Including another URLconf
from django.contrib import admin from django.contrib import admin
from django.urls import path, include # Added include for including app URLs from django.urls import path, include # Added include for including app URLs
from django.http import HttpResponse from django.http import HttpResponse
from django.views.generic import RedirectView
from django.contrib.auth.views import ( from django.contrib.auth.views import (
PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView, PasswordChangeView, PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView, PasswordChangeView,
PasswordChangeDoneView, LogoutView PasswordChangeDoneView, LogoutView
@@ -28,6 +29,7 @@ urlpatterns = [
path("", include("torrent.urls", "torrent")), path("", include("torrent.urls", "torrent")),
path("user/", include("user.urls", "user")), path("user/", include("user.urls", "user")),
path("api/", include("api.urls", "api")), path("api/", include("api.urls", "api")),
path("home", RedirectView.as_view(url="/", permanent=False), name="home"),
# reset password related # reset password related
path("password_reset/", PasswordResetView.as_view(), name="password_reset"), path("password_reset/", PasswordResetView.as_view(), name="password_reset"),

View File

@@ -4,7 +4,7 @@ CORES=$(nproc)
WORKERS=$((2 * CORES + 1)) WORKERS=$((2 * CORES + 1))
cd /app/frontend && yarn dev & cd /app/frontend && yarn dev &
cd /app && uvicorn app.asgi:application --workers $WORKERS --host 0.0.0.0 --port 8000 --lifespan off --loop uvloop --ws websockets --reload & cd /app && python manage.py runserver 0.0.0.0:8000 &
wait -n wait -n

View File

@@ -37,6 +37,11 @@
<v-btn v-bind="props">Manage</v-btn> <v-btn v-bind="props">Manage</v-btn>
</template> </template>
<v-list> <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 href="/password_change/" title="Change password"/>
<v-list-item> <v-list-item>
<v-list-item-action> <v-list-item-action>

View File

@@ -39,7 +39,7 @@ export default {
methods: { methods: {
async fetchFiles(){ async fetchFiles(){
this.loading = true; this.loading = true;
let response = await fetch(`/api/torrent/files?${new URLSearchParams(this.filters)}`); let response = await fetch(`/api/torrent/files/?${new URLSearchParams(this.filters)}`);
this.files = await response.json(); this.files = await response.json();
this.loading = false; this.loading = false;
return this.files; return this.files;

View File

@@ -6,15 +6,9 @@ django-filter
djangorestframework-simplejwt djangorestframework-simplejwt
channels channels
channels_redis channels_redis
celery
pytz pytz
psycopg[binary]
uvicorn
transmission-rpc transmission-rpc
stream-zip stream-zip
anyio anyio
websockets websockets
uvloop uvloop
watchfiles

2
app/requirements-dev.txt Normal file
View File

@@ -0,0 +1,2 @@
-r requirements-common.txt
daphne

View File

@@ -0,0 +1,2 @@
-r requirements-common.txt
uvicorn

BIN
app/static/oxpanel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -1,9 +1,11 @@
{% load django_vite %}<!DOCTYPE html> {% load django_vite %}{% load static %}<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>{% block base_title %}{% block title %}{% endblock %}{% endblock %}</title> <title>{% block base_title %}Oxpanel{% block title %}{% endblock %}{% endblock %}</title>
{% block base_css %} <link rel="icon" type="image/png" href="{% static 'oxpanel.png' %}"/>
{% block base_css %}
{# {% stylesheet_pack 'app' %}#} {# {% stylesheet_pack 'app' %}#}
<link data-n-head="ssr" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"> <link data-n-head="ssr" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
{% block css %}{% endblock %} {% block css %}{% endblock %}

View File

@@ -41,7 +41,6 @@ class TorrentEventConsumer(AsyncJsonWebsocketConsumer):
await self.channel_layer.group_discard("torrent", self.channel_name) await self.channel_layer.group_discard("torrent", self.channel_name)
async def dispatch(self, message): async def dispatch(self, message):
print("dispatch ws :", message)
return await super().dispatch(message) return await super().dispatch(message)
async def receive_json(self, content, **kwargs): async def receive_json(self, content, **kwargs):

View File

@@ -3,6 +3,7 @@ from django.views.generic import CreateView
from django.contrib.auth import login from django.contrib.auth import login
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.db.models import Count, Sum, F, IntegerField from django.db.models import Count, Sum, F, IntegerField
from django.db.models.functions import Coalesce
from rest_framework.viewsets import ModelViewSet, GenericViewSet from rest_framework.viewsets import ModelViewSet, GenericViewSet
from rest_framework import mixins from rest_framework import mixins
@@ -96,9 +97,9 @@ class UserViewSet(mixins.RetrieveModelMixin,
@action(methods=["get"], detail=False) @action(methods=["get"], detail=False)
def user_stats(self, request): def user_stats(self, request):
stats = User.objects.filter(id=request.user.id).aggregate( stats = User.objects.filter(id=request.user.id).aggregate(
total_size=Sum("torrents__size"), total_size=Coalesce(Sum("torrents__size"), 0),
total_torrent=Count("torrents"), total_torrent=Coalesce(Count("torrents"), 0),
total_shared_torrent=Count("torrents_shares", distinct=True), total_shared_torrent=Coalesce(Count("torrents_shares", distinct=True), 0),
) )
disk_usage = shutil.disk_usage("/") disk_usage = shutil.disk_usage("/")

View File

@@ -12,6 +12,9 @@ services:
ports: !reset [] ports: !reset []
app: app:
build:
args:
debug: true
restart: "no" restart: "no"
ports: ports:
- "${DEV_SERVER_PORT:-8080}:${DEV_SERVER_PORT:-8080}" - "${DEV_SERVER_PORT:-8080}:${DEV_SERVER_PORT:-8080}"

View File

@@ -58,6 +58,7 @@ services:
args: args:
puid: ${USER_ID} puid: ${USER_ID}
pgid: ${GROUP_ID} pgid: ${GROUP_ID}
debug: ${DEBUG:-false}
env_file: env_file:
- .env - .env
volumes: volumes: