mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-26 01:43:43 +03:00
added file info, file report
This commit is contained in:
parent
6d65e771d7
commit
c6153b4eaf
|
@ -0,0 +1,57 @@
|
||||||
|
# Generated by Django 4.2 on 2023-04-24 12:03
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
("files", "0021_folder_amount_folder_private"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basefileitem",
|
||||||
|
name="download",
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basefileitem",
|
||||||
|
name="views",
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="FileReport",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created", models.DateTimeField(auto_now_add=True)),
|
||||||
|
(
|
||||||
|
"file",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="reports",
|
||||||
|
to="files.file",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"user",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="reported_file",
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 4.2 on 2023-04-24 12:11
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("files", "0022_basefileitem_download_basefileitem_views_filereport"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefileitem",
|
||||||
|
old_name="download",
|
||||||
|
new_name="downloads",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="filereport",
|
||||||
|
name="user",
|
||||||
|
),
|
||||||
|
]
|
|
@ -5,9 +5,11 @@
|
||||||
CASCADE,
|
CASCADE,
|
||||||
BooleanField,
|
BooleanField,
|
||||||
CharField,
|
CharField,
|
||||||
|
DateTimeField,
|
||||||
FileField,
|
FileField,
|
||||||
ForeignKey,
|
ForeignKey,
|
||||||
IntegerField,
|
IntegerField,
|
||||||
|
Model,
|
||||||
SlugField,
|
SlugField,
|
||||||
TextField,
|
TextField,
|
||||||
)
|
)
|
||||||
|
@ -32,6 +34,9 @@ class BaseFileItem(PolymorphicModel):
|
||||||
created = AutoCreatedField("created")
|
created = AutoCreatedField("created")
|
||||||
modified = AutoLastModifiedField("updated")
|
modified = AutoLastModifiedField("updated")
|
||||||
|
|
||||||
|
views = IntegerField(default=0)
|
||||||
|
downloads = IntegerField(default=0)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ["-modified"]
|
ordering = ["-modified"]
|
||||||
|
|
||||||
|
@ -118,3 +123,11 @@ class FileInTrash(TimeStampedModel):
|
||||||
name = CharField(max_length=200, blank=True)
|
name = CharField(max_length=200, blank=True)
|
||||||
user = ForeignKey("users.User", related_name="trash_files", on_delete=CASCADE)
|
user = ForeignKey("users.User", related_name="trash_files", on_delete=CASCADE)
|
||||||
file = FileField(blank=False, upload_to=trash_file_upload)
|
file = FileField(blank=False, upload_to=trash_file_upload)
|
||||||
|
|
||||||
|
|
||||||
|
class FileReport(Model):
|
||||||
|
created = DateTimeField(auto_now_add=True)
|
||||||
|
file = ForeignKey("files.File", related_name="reports", on_delete=CASCADE)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"report on {self.file}"
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
|
|
||||||
class FileTable(tables.Table):
|
class FileTable(tables.Table):
|
||||||
name = tables.columns.Column("name", linkify=True)
|
name = tables.columns.Column("name", linkify=True)
|
||||||
time = tables.columns.DateTimeColumn(
|
|
||||||
format="H:m:s", accessor="modified", verbose_name="Time"
|
|
||||||
)
|
|
||||||
folder = tables.columns.Column(
|
folder = tables.columns.Column(
|
||||||
linkify=True, accessor="parent", verbose_name="Folder"
|
linkify=True, accessor="parent", verbose_name="Folder"
|
||||||
)
|
)
|
||||||
|
@ -22,7 +19,8 @@ class Meta:
|
||||||
"name",
|
"name",
|
||||||
"created",
|
"created",
|
||||||
"modified",
|
"modified",
|
||||||
"time",
|
"views",
|
||||||
|
"downloads",
|
||||||
"folder",
|
"folder",
|
||||||
"private",
|
"private",
|
||||||
"file",
|
"file",
|
||||||
|
|
|
@ -1,35 +1,37 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from akarpov.files.views import (
|
from akarpov.files.views import (
|
||||||
MyChunkedUploadCompleteView,
|
ChunkedUploadCompleteView,
|
||||||
MyChunkedUploadView,
|
ChunkedUploadView,
|
||||||
TopFolderView,
|
TopFolderView,
|
||||||
delete_file_view,
|
delete_file_view,
|
||||||
|
file_report_list,
|
||||||
file_table,
|
file_table,
|
||||||
file_update,
|
file_update,
|
||||||
files_view,
|
files_view,
|
||||||
folder_create,
|
folder_create,
|
||||||
folder_view,
|
folder_view,
|
||||||
|
report_file,
|
||||||
)
|
)
|
||||||
|
|
||||||
app_name = "files"
|
app_name = "files"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", TopFolderView.as_view(), name="main"),
|
path("", TopFolderView.as_view(), name="main"),
|
||||||
path("table/", file_table, name="table"),
|
path("table/", file_table, name="table"),
|
||||||
|
path("reports/", file_report_list, name="reports"),
|
||||||
path(
|
path(
|
||||||
"api/chunked_upload_complete/",
|
"api/chunked_upload_complete/",
|
||||||
MyChunkedUploadCompleteView.as_view(),
|
ChunkedUploadCompleteView.as_view(),
|
||||||
name="api_chunked_upload_complete",
|
name="api_chunked_upload_complete",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"api/chunked_upload_complete/<str:slug>",
|
"api/chunked_upload_complete/<str:slug>",
|
||||||
MyChunkedUploadCompleteView.as_view(),
|
ChunkedUploadCompleteView.as_view(),
|
||||||
name="api_chunked_upload_complete_folder",
|
name="api_chunked_upload_complete_folder",
|
||||||
),
|
),
|
||||||
path(
|
path("api/chunked_upload/", ChunkedUploadView.as_view(), name="api_chunked_upload"),
|
||||||
"api/chunked_upload/", MyChunkedUploadView.as_view(), name="api_chunked_upload"
|
|
||||||
),
|
|
||||||
path("api/folder/create/", folder_create, name="folder_create"),
|
path("api/folder/create/", folder_create, name="folder_create"),
|
||||||
|
path("api/file/report/<str:slug>", report_file, name="file_report"),
|
||||||
path("api/folder/create/<str:slug>", folder_create, name="sub_folder_create"),
|
path("api/folder/create/<str:slug>", folder_create, name="sub_folder_create"),
|
||||||
path("<str:slug>", files_view, name="view"),
|
path("<str:slug>", files_view, name="view"),
|
||||||
path("<str:slug>/update", file_update, name="update"),
|
path("<str:slug>/update", file_update, name="update"),
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
)
|
)
|
||||||
from akarpov.files.filters import FileFilter
|
from akarpov.files.filters import FileFilter
|
||||||
from akarpov.files.forms import FileForm, FolderForm
|
from akarpov.files.forms import FileForm, FolderForm
|
||||||
from akarpov.files.models import BaseFileItem, File, Folder
|
from akarpov.files.models import BaseFileItem, File, FileReport, Folder
|
||||||
from akarpov.files.previews import extensions, meta, meta_extensions, previews
|
from akarpov.files.previews import extensions, meta, meta_extensions, previews
|
||||||
from akarpov.files.services.preview import get_base_meta
|
from akarpov.files.services.preview import get_base_meta
|
||||||
from akarpov.files.tables import FileTable
|
from akarpov.files.tables import FileTable
|
||||||
|
@ -91,6 +91,9 @@ def get_queryset(self):
|
||||||
return BaseFileItem.objects.filter(parent=folder)
|
return BaseFileItem.objects.filter(parent=folder)
|
||||||
|
|
||||||
|
|
||||||
|
folder_view = FileFolderView.as_view()
|
||||||
|
|
||||||
|
|
||||||
class FileUpdateView(LoginRequiredMixin, UpdateView):
|
class FileUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
model = File
|
model = File
|
||||||
form_class = FileForm
|
form_class = FileForm
|
||||||
|
@ -204,10 +207,7 @@ def get_redirect_url(self, *args, **kwargs):
|
||||||
delete_file_view = DeleteFileView.as_view()
|
delete_file_view = DeleteFileView.as_view()
|
||||||
|
|
||||||
|
|
||||||
folder_view = FileFolderView.as_view()
|
class ChunkedUploadView(ChunkedUploadView):
|
||||||
|
|
||||||
|
|
||||||
class MyChunkedUploadView(ChunkedUploadView):
|
|
||||||
model = ChunkedUpload
|
model = ChunkedUpload
|
||||||
field_name = "the_file"
|
field_name = "the_file"
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ def check_permissions(self, request):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MyChunkedUploadCompleteView(ChunkedUploadCompleteView):
|
class ChunkedUploadCompleteView(ChunkedUploadCompleteView):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.message = {}
|
self.message = {}
|
||||||
|
@ -286,3 +286,26 @@ def get_queryset(self, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
file_table = FileTableView.as_view()
|
file_table = FileTableView.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
class ReportFileView(RedirectView):
|
||||||
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
|
file = get_object_or_404(File, slug=kwargs["slug"])
|
||||||
|
FileReport.objects.create(file=file)
|
||||||
|
return reverse("files:view", kwargs={"slug": file.slug})
|
||||||
|
|
||||||
|
|
||||||
|
report_file = ReportFileView.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
class ListFileReports(LoginRequiredMixin, ListView):
|
||||||
|
model = FileReport
|
||||||
|
template_name = "files/reports.html"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if self.request.user.is_superuser:
|
||||||
|
return FileReport.objects.all()
|
||||||
|
return FileReport.objects.none()
|
||||||
|
|
||||||
|
|
||||||
|
file_report_list = ListFileReports.as_view()
|
||||||
|
|
|
@ -52,10 +52,10 @@
|
||||||
</nav>
|
</nav>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="d-flex justify-content-end me-5">
|
|
||||||
<a class="me-5" href="{% url 'files:table' %}">View in table view</a>
|
|
||||||
</div>
|
|
||||||
{% if request.user.is_authenticated and is_folder_owner %}
|
{% if request.user.is_authenticated and is_folder_owner %}
|
||||||
|
<div class="d-flex justify-content-end me-5">
|
||||||
|
<a class="me-5" href="{% url 'files:table' %}">table view</a>
|
||||||
|
</div>
|
||||||
<div class="col-lg-2 col-xxl-2 col-md-4 col-sm-6 col-xs-12 mb-3 m-3 d-flex align-items-stretch card">
|
<div class="col-lg-2 col-xxl-2 col-md-4 col-sm-6 col-xs-12 mb-3 m-3 d-flex align-items-stretch card">
|
||||||
<div class="card-body d-flex flex-column justify-content-center align-items-center">
|
<div class="card-body d-flex flex-column justify-content-center align-items-center">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
14
akarpov/templates/files/reports.html
Normal file
14
akarpov/templates/files/reports.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load humanize %}
|
||||||
|
|
||||||
|
<div class="list-group">
|
||||||
|
{% for file in filereport_list %}
|
||||||
|
<a href="{{ file.file.get_absolute_url }}" class="list-group-item list-group-item-action">
|
||||||
|
<div class="d-flex w-100 justify-content-between">
|
||||||
|
<h5 class="mb-1">{{ file.file.name }}</h5>
|
||||||
|
<small>{{ file.created | naturaltime }}</small>
|
||||||
|
</div>
|
||||||
|
<small>{{ file.file.file_type }}</small>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="justify-content-end d-flex">
|
<div class="justify-content-end d-flex">
|
||||||
<a href="{% url 'files:main' %}">View in folder view</a>
|
<a href="{% url 'files:main' %}">folder view</a>
|
||||||
</div>
|
</div>
|
||||||
<form class="mb-4 p-2" >
|
<form class="mb-4 p-2" >
|
||||||
<div class="row d-flex">
|
<div class="row d-flex">
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
</button>
|
</button>
|
||||||
{% endif %}</p>
|
{% endif %}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<a class="text-danger mt-2" style="text-decoration: none" href="{% url 'files:file_report' slug=file.slug %}"><i class="bi bi-flag-fill"></i>report file</a>
|
||||||
<div class="mt-4 text-center justify-content-sm-evenly justify-content-md-start gap-3 align-items-md-start align-items-sm-center d-flex">
|
<div class="mt-4 text-center justify-content-sm-evenly justify-content-md-start gap-3 align-items-md-start align-items-sm-center d-flex">
|
||||||
<a class="btn btn-success fs-6" href="{{ file.file.url }}" download><i class="bi bi-download"></i> Download</a>
|
<a class="btn btn-success fs-6" href="{{ file.file.url }}" download><i class="bi bi-download"></i> Download</a>
|
||||||
{% if has_perm %}
|
{% if has_perm %}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user