added file previews, file page

This commit is contained in:
Alexander Karpov 2023-04-11 22:10:54 +03:00
parent a30f402f18
commit 8a995a8ca5
11 changed files with 144 additions and 7 deletions

View File

@ -0,0 +1,3 @@
from . import image, video
previews = {"video": {"mp4": video.mp4.view}, "image": {"jpeg": image.jpeg.view}}

View File

@ -0,0 +1 @@
from . import jpeg # noqa

View File

@ -0,0 +1,35 @@
from akarpov.files.models import File
def view(file: File) -> (str, str):
static = """
<link href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css" rel="stylesheet">
"""
content = (
f"""
<div>
<img id="image" class="img-fluid" src="{file.file.url}" alt="Picture">
</div>
<script src="/static/js/jquery.js"></script>
"""
+ """
<script src="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js">
var $image = $('#image');
$image.viewer({
inline: true,
viewed: function() {
$image.viewer('zoomTo', 1);
}
});
// Get the Viewer.js instance after initialized
var viewer = $image.data('viewer');
// View a list of images
$('#images').viewer();
</script>
"""
)
return static, content

View File

@ -0,0 +1 @@
from . import mp4 # noqa

View File

@ -0,0 +1,20 @@
from akarpov.files.models import File
def view(file: File) -> (str, str):
static = """
<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}'
data-setup='{data}'>
<source src="{file.file.url}" type='video/mp4' />
</video>
<script src="https://vjs.zencdn.net/8.0.4/video.min.js"></script>
"""
return static, content

View File

@ -84,7 +84,8 @@ def create_preview(file_path: str) -> str:
def get_file_mimetype(file_path: str) -> str: def get_file_mimetype(file_path: str) -> str:
return magic.from_file(file_path) mime = magic.Magic(mime=True)
return mime.from_file(file_path)
def get_description(file_path: str) -> str: def get_description(file_path: str) -> str:

View File

@ -31,7 +31,7 @@ def process_file(pk: int):
) )
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
file.type = get_file_mimetype(file.file.path) file.file_type = get_file_mimetype(file.file.path)
descr = None descr = None
try: try:
descr = get_description(file.file.path) descr = get_description(file.file.path)

View File

@ -11,10 +11,12 @@
ChunkedUploadView, ChunkedUploadView,
) )
from akarpov.files.models import File, Folder from akarpov.files.models import File, Folder
from akarpov.files.previews import previews
class TopFolderView(LoginRequiredMixin, ListView): class TopFolderView(LoginRequiredMixin, ListView):
template_name = "files/list.html" template_name = "files/list.html"
paginate_by = 20
model = File model = File
def get_queryset(self): def get_queryset(self):
@ -33,6 +35,20 @@ class FileView(DetailView):
model = File model = File
slug_field = "slug" slug_field = "slug"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["has_perm"] = self.object.user == self.request.user
static = ""
content = ""
if self.object.file_type:
t1, t2 = self.object.file_type.split("/")
if t1 in previews:
if t2 in previews[t1]:
static, content = previews[t1][t2](self.object)
context["preview_static"] = static
context["preview_content"] = content
return context
files_view = FileView.as_view() files_view = FileView.as_view()

View File

@ -51,7 +51,7 @@
</li> </li>
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<li> <li>
<a href="{% url 'files:main' %}" class="{% active_link 'files' %} text-muted nav-link px-sm-0 px-2"> <a href="{% url 'files:main' %}" class="{% active_link 'files:main' %} text-muted nav-link px-sm-0 px-2">
<i class="fs-5 bi-folder-fill"></i><span class="ms-1 d-none d-sm-inline">Files</span></a> <i class="fs-5 bi-folder-fill"></i><span class="ms-1 d-none d-sm-inline">Files</span></a>
</li> </li>
{% endif %} {% endif %}

View File

@ -57,8 +57,8 @@
</symbol> </symbol>
</defs> </defs>
</svg> </svg>
<p class="text-break" id="progress-message"></p>
<div id="progress" class="progress w-100" style="display: none" role="progressbar" aria-label="Warning example" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"> <div id="progress" class="progress w-100" style="display: none" role="progressbar" aria-label="Warning example" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
<h1 id="progress-message"></h1>
<div id="progress-bar" class="progress-bar text-bg-warning" style="width: 0%">0%</div> <div id="progress-bar" class="progress-bar text-bg-warning" style="width: 0%">0%</div>
</div> </div>
<div id="messages"></div> <div id="messages"></div>
@ -72,11 +72,36 @@
<div class="align-self-stretch align-items-center justify-content-center d-flex flex-column fill-height controlsdiv"> <div class="align-self-stretch align-items-center justify-content-center d-flex flex-column fill-height controlsdiv">
<img src="{{ file.file_image_url }}" class="img-fluid" alt=""> <img src="{{ file.file_image_url }}" class="img-fluid" alt="">
</div> </div>
<a href="{% url 'files:view' file.slug %}" class="stretched-link"></a>
<p class="card-text mb-4 mt-2 ms-3"><small class="text-muted">{{ file.modified | naturaltime }}</small></p> <p class="card-text mb-4 mt-2 ms-3"><small class="text-muted">{{ file.modified | naturaltime }}</small></p>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% if page_obj.has_other_pages %}
<div class="btn-group" role="group" aria-label="Item pagination">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}" class="btn btn-outline-warning">&laquo;</a>
{% endif %}
{% for page_number in page_obj.paginator.page_range %}
{% if page_obj.number == page_number %}
<button class="btn btn-outline-warning active">
<span>{{ page_number }} <span class="sr-only">(current)</span></span>
</button>
{% else %}
<a href="?page={{ page_number }}" class="btn btn-outline-warning">
{{ page_number }}
</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}" class="btn btn-outline-warning">&raquo;</a>
{% endif %}
</div>
{% endif %}
{% endblock %} {% endblock %}
{% block inline_javascript %} {% block inline_javascript %}
@ -157,15 +182,14 @@
add: function(e, data) { // Called before starting upload add: function(e, data) { // Called before starting upload
if (cur !== true){ if (cur !== true){
cur = true cur = true
console.log("add", data.files[0])
form_data.splice(1); form_data.splice(1);
calculate_md5(data.files[0], 1000000); calculate_md5(data.files[0], 1000000);
data.submit(); data.submit();
$("#progress").css("display", "flex"); $("#progress").css("display", "flex");
$("#progress-message").text("loading file: " + data.files[0].name);
} }
}, },
chunkdone: function (e, data) { // Called after uploading each chunk chunkdone: function (e, data) { // Called after uploading each chunk
console.log("chunkdone", data.files[0])
if (form_data.length < 2) { if (form_data.length < 2) {
form_data.push( form_data.push(
{"name": "upload_id", "value": data.result.upload_id} {"name": "upload_id", "value": data.result.upload_id}
@ -177,7 +201,10 @@
sel.text(progress + "%"); sel.text(progress + "%");
}, },
done: function (e, data) { // Called when the file has completely uploaded done: function (e, data) { // Called when the file has completely uploaded
console.log("done", data.files[0]) var progress = 100;
let sel = $("#progress-bar");
sel.css("width", progress + "%");
sel.text(progress + "%");
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: "{% url 'files:api_chunked_upload_complete' %}", url: "{% url 'files:api_chunked_upload_complete' %}",

View File

@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block javascript %}
{% autoescape off %}
{{ preview_static }}
{% endautoescape %}
{% endblock %}
{% block content %}
<div class="row m-2">
<div class="col-auto">
<h1 class="fs-1">{{ file.name }}</h1>
{% 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 %}
{{ file.user.username }}</a></p>
{% endif %}
<p class="mt-2">Last updated: {{ file.modified|date:"d.m.Y" }} {{ file.modified|time:"H:i" }}</p>
<p>File size: {{ file.file_size | filesizeformat }}</p>
{% if file.file_type %}
<p>File type: {{ file.file_type }}</p>
{% endif %}
{% if file.description %}
<p>{{ file.description }}</p>
{% endif %}
</div>
<div class="col-auto">
{% autoescape off %}
{{ preview_content }}
{% endautoescape %}
</div>
</div>
{% endblock %}