Skip to content

Commit

Permalink
Multi upload (#115)
Browse files Browse the repository at this point in the history
* Add history of uploads

* Update page for form and history

* Fix progress bar
  • Loading branch information
meomancer authored Jan 26, 2024
1 parent 3778a16 commit 5ed6bb0
Show file tree
Hide file tree
Showing 10 changed files with 578 additions and 56 deletions.
2 changes: 2 additions & 0 deletions admin/upload_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ def resume_upload(modeladmin, request, queryset):
@admin.action(description='Restart upload.')
def restart_upload(modeladmin, request, queryset):
for upload_session in queryset:
upload_session.is_canceled = False
upload_session.save()
upload_session.run_in_background(restart=True)


Expand Down
26 changes: 26 additions & 0 deletions api/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# coding=utf-8

from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response


class Pagination(PageNumberPagination):
"""Pagination for API."""

page_size_query_param = 'page_size'

def get_paginated_response_data(self, data):
"""Return paginated only data."""
return {
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'count': self.page.paginator.count,
'page': self.page.number,
'total_page': self.page.paginator.num_pages,
'page_size': self.page.paginator.per_page,
'results': data,
}

def get_paginated_response(self, data):
"""Response for pagination."""
return Response(self.get_paginated_response_data(data))
32 changes: 29 additions & 3 deletions api/upload_session.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
from django.core.exceptions import PermissionDenied
from django.http import JsonResponse, Http404, HttpResponse
from django.views.generic.base import View
from rest_framework.generics import ListAPIView
from rest_framework.permissions import IsAuthenticated

from gwml2.api.pagination import Pagination
from gwml2.models.upload_session import UploadSession
from gwml2.serializer.upload_session import UploadSessionSerializer


class UploadSessionListApiView(ListAPIView):
"""Return List of upload session."""

permission_classes = (IsAuthenticated,)
pagination_class = Pagination
serializer_class = UploadSessionSerializer

def get_queryset(self):
"""Return queryset of API."""
return UploadSession.objects.filter(
uploader=self.request.user.id
)


class UploadSessionApiView(View):
"""
Return status of the upload session
Expand All @@ -13,9 +31,7 @@ class UploadSessionApiView(View):
def get(self, request, token, *args):

try:
session = UploadSession.objects.get(
token=token
)
session = UploadSession.objects.get(token=token)
output = UploadSessionSerializer(session).data
output.update(session.progress_status())
return JsonResponse(output)
Expand All @@ -26,6 +42,12 @@ def post(self, request, token, *args):
"""Resume the upload."""
try:
session = UploadSession.objects.get(token=token)
if not session.uploader:
raise PermissionDenied()
if request.user.id != session.uploader:
raise PermissionDenied()
session.is_canceled = False
session.save()
session.run_in_background()
return HttpResponse('ok')
except UploadSession.DoesNotExist:
Expand All @@ -39,6 +61,10 @@ def post(self, request, token, *args):
"""Resume the upload."""
try:
session = UploadSession.objects.get(token=token)
if not session.uploader:
raise PermissionDenied()
if request.user.id != session.uploader:
raise PermissionDenied()
session.is_canceled = True
session.save()
return HttpResponse('ok')
Expand Down
6 changes: 5 additions & 1 deletion serializer/upload_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@

class UploadSessionSerializer(serializers.ModelSerializer):
organisation = serializers.SerializerMethodField()
file_url = serializers.SerializerMethodField()
report_filename = serializers.SerializerMethodField()
uploaded_at = serializers.SerializerMethodField()

def get_file_url(self, obj: UploadSession):
return obj.upload_file.url

def get_organisation(self, obj: UploadSession):
return obj.organisation.name if obj.organisation else '-'

Expand All @@ -23,5 +27,5 @@ class Meta:
fields = [
'id', 'organisation', 'token', 'uploaded_at', 'status', 'progress',
'filename', 'category', 'report_filename', 'is_processed',
'is_canceled', 'task_status', 'step'
'is_canceled', 'task_status', 'step', 'file_url'
]
1 change: 1 addition & 0 deletions tasks/uploader/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def __init__(self, upload_session: UploadSession, restart: bool = False):
except UploadSessionCancelled:
self.upload_session.update_step('Create report')
self.upload_session.create_report_excel()
self.upload_session.update_step('Cancelled')
return

self.upload_session.update_step('Create report')
Expand Down
173 changes: 173 additions & 0 deletions templates/upload_session/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% csrf_token %}
{% block page_title %}
<h1>Upload Excel File For Well Data.</h1>
{% endblock page_title %}

{% block extra_head %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
{% endblock %}
{% block body %}
<style>
.page-header {
font-size: 17pt;
}

.form-group p, .form-group .p {
border: 1px solid lightgrey;
padding: 15px;
}

.form-group p:hover {
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.10);
}

.tab-pane {
padding: 40px;
border-bottom: 1px solid rgb(221, 221, 221);
border-left: 1px solid rgb(221, 221, 221);
border-right: 1px solid rgb(221, 221, 221);
}

.template-indicator {
margin-bottom: 20px;
font-style: italic;
color: grey;
}

.template-indicator a {
font-weight: 700;
}

.notes span {
display: inline-block;
padding: 5px 10px;
font-weight: 700;
}

.notes .added {
background-color: #48b14f;
color: white;
}

.notes .error {
background-color: #ca3232;
color: white;
}

.notes .skipped {
background-color: #ffef44;
}

select {
cursor: pointer;
}

select,
textarea {
width: 100%;
}

.multivalue .multivalue-selection div {
float: none !important;
width: fit-content;
display: inline-block;
}

.well:hover {
cursor: pointer;
opacity: 0.7;
}

.progress {
border-radius: 0 !important;
height: 2rem !important;
position: relative;
width: 400px;
margin-bottom: 0 !important;
}

.upload-progress {
text-align: left;
box-sizing: border-box;
}

.msgapi .progress-bar {
background-color: white;
color: black;
box-shadow: unset;
border: 1px solid #ddd;
}

.progress-bar-success {
position: absolute;
top: 0;
left: 0;
}

.msgapi .progress-bar-success {
background-color: #398439 !important;
}

.upload-progress-text {
padding: 8px 0;
height: 100%;
text-align: left;
white-space: nowrap;
overflow: hidden;
}

.upload-progress-text {
color: white;
}

.upload-progress-text.bottom {
color: var(--gn-main-color, #000);
}

button:disabled {
color: #555;
}
</style>
<script>
function mainTabChange(url) {
window.location.href = url;
}
</script>
<div class="container">
<br>
<ul class="nav nav-tabs" id="mainTab" role="tablist">
<li class="nav-item {% if 'history' not in request.path %}active{% endif %}">
<a class="nav-link active"
data-toggle="tab"
href="#batch-form"
role="tab"
aria-controls="home"
aria-selected="true"
onclick="mainTabChange('{% url 'well_upload_view' %}')"
>
{% trans "Batch Upload Form" %}
</a>
</li>
<li class="nav-item {% if 'history' in request.path %}active{% endif %}">
<a class="nav-link"
data-toggle="tab"
href="#history" role="tab"
aria-controls="profile"
aria-selected="false"
onclick="mainTabChange('{% url 'well_upload_history_view' %}')"
>
{% trans "Past Uploads" %}
</a>
</li>
</ul>
<br>
{% block content %}
{% endblock %}
</div>
{% block outside_content %}
{% endblock %}
{% endblock %}
Loading

0 comments on commit 5ed6bb0

Please sign in to comment.