mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-25 12:53:43 +03:00
updated previews, fixed short links, added og tags, download delete
This commit is contained in:
parent
e7d78d59ec
commit
d4f68935a1
|
@ -9,7 +9,7 @@
|
|||
"wav": audio.basic.view,
|
||||
"webm": audio.basic.view,
|
||||
},
|
||||
"video": {"mp4": video.mp4.view},
|
||||
"video": {"mp4": video.mp4.view, "quicktime": video.basic.view},
|
||||
"image": {
|
||||
"jpeg": image.basic.view,
|
||||
"png": image.basic.view,
|
||||
|
@ -17,4 +17,9 @@
|
|||
},
|
||||
}
|
||||
|
||||
extensions = {"mp4": video.mp4.view, "mp3": audio.basic.view, "avif": image.basic.view}
|
||||
extensions = {
|
||||
"mp4": video.mp4.view,
|
||||
"mp3": audio.basic.view,
|
||||
"avif": image.basic.view,
|
||||
"mov": video.basic.view,
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
|
||||
def view(file: File) -> (str, str):
|
||||
static = """
|
||||
static = f"""
|
||||
<meta property="og:title" content="{file.name}" />
|
||||
"""
|
||||
content = (
|
||||
"""
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
|
||||
|
||||
def view(file: File) -> (str, str):
|
||||
static = """
|
||||
static = (
|
||||
f"""
|
||||
<meta property="og:title" content="{file.name}" />
|
||||
"""
|
||||
+ """
|
||||
<style>
|
||||
#canvas {
|
||||
position: absolute;
|
||||
|
@ -13,6 +17,7 @@ def view(file: File) -> (str, str):
|
|||
}
|
||||
</style>
|
||||
"""
|
||||
)
|
||||
content = (
|
||||
"""
|
||||
<div id="container">
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
|
||||
def view(file: File) -> (str, str):
|
||||
static = """
|
||||
static = f"""
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css" rel="stylesheet">
|
||||
<meta property="og:title" content="{file.name}" />
|
||||
"""
|
||||
content = (
|
||||
f"""
|
||||
|
|
|
@ -1 +1 @@
|
|||
from . import mp4 # noqa
|
||||
from . import basic, mp4 # noqa
|
||||
|
|
26
akarpov/files/previews/video/basic.py
Normal file
26
akarpov/files/previews/video/basic.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from akarpov.files.models import File
|
||||
|
||||
|
||||
def view(file: File) -> (str, str):
|
||||
static = f"""
|
||||
<meta property="og:title" content="{file.name}" />
|
||||
<meta property="og:type" content="video.movie" />
|
||||
<meta property="og:video" content="dev2.akarpov.ru/{file.file.url}" />
|
||||
<meta property="og:video:type" content="{file.file_type}" />
|
||||
<meta property="og:video:width" content="720" />
|
||||
<meta property="og:video:height" content="480" />
|
||||
<link href="https://vjs.zencdn.net/8.0.4/video-js.css" rel="stylesheet" />
|
||||
"""
|
||||
data = """"playbackRates": [0.5, 1, 1.5, 2], "responsive": true }"""
|
||||
content = f"""
|
||||
|
||||
<video id="my_video_1" class="video-js vjs-default-skin" height="500px"
|
||||
controls poster='{file.preview.url if file.preview else ''}'
|
||||
data-setup='{data}'>
|
||||
<source src="{file.file.url}" type='{file.file_type}' />
|
||||
</video>
|
||||
|
||||
<script src="https://vjs.zencdn.net/8.0.4/video.min.js"></script>
|
||||
"""
|
||||
|
||||
return static, content
|
|
@ -2,7 +2,13 @@
|
|||
|
||||
|
||||
def view(file: File) -> (str, str):
|
||||
static = """
|
||||
static = f"""
|
||||
<meta property="og:title" content="{file.name}" />
|
||||
<meta property="og:type" content="video.movie" />
|
||||
<meta property="og:video" content="{file.file.url}" />
|
||||
<meta property="og:video:type" content="{file.file_type}" />
|
||||
<meta property="og:video:width" content="720" />
|
||||
<meta property="og:video:height" content="480" />
|
||||
<link href="https://vjs.zencdn.net/8.0.4/video-js.css" rel="stylesheet" />
|
||||
"""
|
||||
data = """"playbackRates": [0.5, 1, 1.5, 2], "responsive": true }"""
|
||||
|
@ -11,7 +17,7 @@ def view(file: File) -> (str, str):
|
|||
<video id="my_video_1" class="video-js vjs-default-skin" height="500px"
|
||||
controls poster='{file.preview.url if file.preview else ''}'
|
||||
data-setup='{data}'>
|
||||
<source src="{file.file.url}" type='video/mp4' />
|
||||
<source src="{file.file.url}" type='{file.file_type}' />
|
||||
</video>
|
||||
|
||||
<script src="https://vjs.zencdn.net/8.0.4/video.min.js"></script>
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
from django.core.files import File
|
||||
|
||||
from akarpov.files.models import File as FileModel
|
||||
from akarpov.files.services.preview import (
|
||||
create_preview,
|
||||
get_description,
|
||||
get_file_mimetype,
|
||||
)
|
||||
from akarpov.files.services.preview import create_preview, get_file_mimetype
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
@ -32,18 +28,7 @@ def process_file(pk: int):
|
|||
except Exception as e:
|
||||
logger.error(e)
|
||||
file.file_type = get_file_mimetype(file.file.path)
|
||||
descr = None
|
||||
try:
|
||||
descr = get_description(file.file.path)
|
||||
if descr:
|
||||
with open(descr, encoding="utf-8") as f:
|
||||
data = f.read()
|
||||
file.description = data
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
file.save(update_fields=["preview", "name", "file_type", "description"])
|
||||
file.save(update_fields=["preview", "name", "file_type"])
|
||||
if pth and os.path.isfile(pth):
|
||||
os.remove(pth)
|
||||
if descr and os.path.isfile(descr):
|
||||
os.remove(descr)
|
||||
return pk
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
MyChunkedUploadCompleteView,
|
||||
MyChunkedUploadView,
|
||||
TopFolderView,
|
||||
delete_file_view,
|
||||
files_view,
|
||||
folder_view,
|
||||
)
|
||||
|
@ -22,5 +23,6 @@
|
|||
"api/chunked_upload/", MyChunkedUploadView.as_view(), name="api_chunked_upload"
|
||||
),
|
||||
path("<str:slug>", files_view, name="view"),
|
||||
path("<str:slug>/delete", delete_file_view, name="delete"),
|
||||
path("f/<str:slug>", folder_view, name="folder"),
|
||||
]
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import os
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.views.generic import DetailView, ListView
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.views.generic import DetailView, ListView, RedirectView
|
||||
from django.views.generic.base import TemplateView
|
||||
|
||||
from akarpov.contrib.chunked_upload.exceptions import ChunkedUploadError
|
||||
|
@ -58,6 +60,17 @@ def get_context_data(self, **kwargs):
|
|||
files_view = FileView.as_view()
|
||||
|
||||
|
||||
class DeleteFileView(LoginRequiredMixin, RedirectView):
|
||||
def get_redirect_url(self, *args, **kwargs):
|
||||
file = get_object_or_404(File, slug=kwargs["slug"])
|
||||
if file.user == self.request.user:
|
||||
file.delete()
|
||||
return reverse("files:main")
|
||||
|
||||
|
||||
delete_file_view = DeleteFileView.as_view()
|
||||
|
||||
|
||||
class FileFolderView(DetailView):
|
||||
template_name = "files/folder.html"
|
||||
model = Folder
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
||||
<li>
|
||||
<a href="{% url 'account_signup' %}" class="text-muted nav-link px-sm-0 px-2 {% active_link 'account_signup' %}">
|
||||
<i class="fs-5 bi-person"></i><span class="ms-1 d-none d-sm-inline">Sign up</span> </a>
|
||||
<i class="fs-5 bi-person"></i><span class="ms-1 d-none d-sm-inline">Register</span> </a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="row m-2">
|
||||
<div class="col-md-4 col-sm-6">
|
||||
<h1 class="fs-1">{{ file.name }}</h1>
|
||||
<h1 class="fs-1 text-break mb-4">{{ file.name }}</h1>
|
||||
<div class="col-md-4 col-sm-6 col-xs-auto">
|
||||
{% if not has_perm %}
|
||||
<p>Uploaded by: <a href="{% url 'users:detail' file.user.username %}">
|
||||
{% if file.user.image_cropped %}<img class="rounded" width="20" src="{{ file.user.image_cropped.url }}" alt=""> {% endif %}
|
||||
|
@ -23,11 +23,30 @@
|
|||
{% if file.description %}
|
||||
<p>{{ file.description }}</p>
|
||||
{% endif %}
|
||||
{% if file.private %}
|
||||
<p>File is private</p>
|
||||
{% else %}
|
||||
<p>File is public{% if file.short_link %},
|
||||
<a href="{{ file.short_link.get_absolute_url }}">short link</a><button class="btn" data-clipboard-text="{{ request.get_host }}{{ file.short_link.get_absolute_url }}">
|
||||
<i style="font-size: 0.8em" class="bi bi-clipboard ml-2"></i>
|
||||
</button>
|
||||
{% endif %}</p>
|
||||
{% endif %}
|
||||
<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>
|
||||
{% if has_perm %}
|
||||
<a class="btn btn-danger fs-6" href="{% url 'files:delete' slug=file.slug %}"><i class="bi bi-trash"></i> Delete</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-8 col-sm-10">
|
||||
</div>
|
||||
<div class="col-md-8 col-sm-10 col-xs-auto">
|
||||
{% autoescape off %}
|
||||
{{ preview_content }}
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.10/clipboard.min.js"></script>
|
||||
<script>
|
||||
new ClipboardJS('.btn');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -48,12 +48,57 @@ def create_model_link(sender, instance, created, **kwargs):
|
|||
return
|
||||
if hasattr(instance, "creator"):
|
||||
link.creator = instance.creator
|
||||
elif hasattr(instance, "user"):
|
||||
link.creator = instance.user
|
||||
elif hasattr(instance, "owner"):
|
||||
link.creator = instance.owner
|
||||
|
||||
link.save()
|
||||
instance.short_link = link
|
||||
instance.save()
|
||||
|
||||
|
||||
def update_model_link(sender, instance, **kwargs):
|
||||
model = sender
|
||||
if instance.id:
|
||||
previous = model.objects.get(id=instance.id)
|
||||
prev_private = False
|
||||
cur_private = False
|
||||
if hasattr(instance, "private"):
|
||||
if instance.private:
|
||||
cur_private = True
|
||||
if hasattr(instance, "public"):
|
||||
if not instance.public:
|
||||
cur_private = True
|
||||
if hasattr(previous, "private"):
|
||||
if previous.private:
|
||||
prev_private = True
|
||||
if hasattr(previous, "public"):
|
||||
if not previous.public:
|
||||
prev_private = True
|
||||
|
||||
if prev_private != cur_private:
|
||||
if prev_private:
|
||||
# instance was private, public now, need to create short link
|
||||
if hasattr(instance, "short_link"):
|
||||
if not instance.short_link:
|
||||
link = Link(source=instance.get_absolute_url())
|
||||
if hasattr(instance, "creator"):
|
||||
link.creator = instance.creator
|
||||
elif hasattr(instance, "user"):
|
||||
link.creator = instance.user
|
||||
elif hasattr(instance, "owner"):
|
||||
link.creator = instance.owner
|
||||
link.save()
|
||||
instance.short_link = link
|
||||
else:
|
||||
# instance was public, private now, need to delete short link
|
||||
if hasattr(previous, "short_link"):
|
||||
if previous.short_link:
|
||||
previous.short_link.delete()
|
||||
instance.short_link = None
|
||||
|
||||
|
||||
class ShortLink(SlugModel):
|
||||
short_link: Link | None = models.ForeignKey(
|
||||
"shortener.Link", blank=True, null=True, on_delete=models.SET_NULL
|
||||
|
@ -63,6 +108,7 @@ class ShortLink(SlugModel):
|
|||
def __init_subclass__(cls, **kwargs):
|
||||
super().__init_subclass__(**kwargs)
|
||||
models.signals.post_save.connect(create_model_link, sender=cls)
|
||||
models.signals.pre_save.connect(update_model_link, sender=cls)
|
||||
|
||||
@abstractmethod
|
||||
def get_absolute_url(self):
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
default="Lm4alUqtub6qQT4MnV4NmtXQP02RCBtmGj1bJhyDho07Bkjk9WFZxGtwpnLNQGJQ",
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"]
|
||||
ALLOWED_HOSTS = ["*"]
|
||||
CSRF_TRUSTED_ORIGINS = ["http://127.0.0.1", "https://*.akarpov.ru"]
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue
Block a user