Show average run times for imports

This should give users a sense of when to start wondering if their
import isn't running after all.
This commit is contained in:
Mouse Reeve 2022-11-05 12:49:11 -07:00
parent 01d5274ebb
commit 4806a6273e
2 changed files with 61 additions and 15 deletions

View file

@ -7,12 +7,28 @@
{% block content %}
<div class="block">
<h1 class="title">{% trans "Import Books" %}</h1>
{% if recent_avg_hours or recent_avg_minutes %}
<div class="notification">
<p>
{% if recent_avg_hours %}
{% blocktrans trimmed with hours=recent_avg_hours|floatformat:0|intcomma %}
On average, recent imports have taken {{ hours }} hours.
{% endblocktrans %}
{% else %}
{% blocktrans trimmed with minutes=recent_avg_minutes|floatformat:0|intcomma %}
On average, recent imports have taken {{ minutes }} minutes.
{% endblocktrans %}
{% endif %}
</p>
</div>
{% endif %}
<form class="box" name="import" action="/import" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="columns">
<div class="column is-half">
<div class="field">
<label class="label" for="source">
{% trans "Data source:" %}
@ -21,19 +37,19 @@
<div class="select">
<select name="source" id="source" aria-describedby="desc_source">
<option value="Goodreads" {% if current == 'Goodreads' %}selected{% endif %}>
Goodreads (CSV)
{% trans "Goodreads (CSV)" %}
</option>
<option value="Storygraph" {% if current == 'Storygraph' %}selected{% endif %}>
Storygraph (CSV)
{% trans "Storygraph (CSV)" %}
</option>
<option value="LibraryThing" {% if current == 'LibraryThing' %}selected{% endif %}>
LibraryThing (TSV)
{% trans "LibraryThing (TSV)" %}
</option>
<option value="OpenLibrary" {% if current == 'OpenLibrary' %}selected{% endif %}>
OpenLibrary (CSV)
{% trans "OpenLibrary (CSV)" %}
</option>
<option value="Calibre" {% if current == 'Calibre' %}selected{% endif %}>
Calibre (CSV)
{% trans "Calibre (CSV)" %}
</option>
</select>
</div>
@ -81,5 +97,7 @@
<li><a href="{% url 'import-status' job.id %}">{{ job.created_date | naturaltime }}</a></li>
{% endfor %}
</ul>
{% include 'snippets/pagination.html' with page=jobs path=request.path %}
</div>
{% endblock %}

View file

@ -1,10 +1,14 @@
""" import books from another app """
from io import TextIOWrapper
import datetime
from django.contrib.auth.decorators import login_required
from django.db.models import Avg, ExpressionWrapper, F, fields
from django.core.paginator import Paginator
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views import View
@ -17,6 +21,7 @@ from bookwyrm.importers import (
StorygraphImporter,
OpenLibraryImporter,
)
from bookwyrm.settings import PAGE_LENGTH
# pylint: disable= no-self-use
@method_decorator(login_required, name="dispatch")
@ -25,16 +30,39 @@ class Import(View):
def get(self, request):
"""load import page"""
return TemplateResponse(
request,
"import/import.html",
{
"import_form": forms.ImportForm(),
"jobs": models.ImportJob.objects.filter(user=request.user).order_by(
"-created_date"
),
},
jobs = models.ImportJob.objects.filter(user=request.user).order_by(
"-created_date"
)
paginated = Paginator(jobs, PAGE_LENGTH)
page = paginated.get_page(request.GET.get("page"))
data = {
"import_form": forms.ImportForm(),
"jobs": page,
"page_range": paginated.get_elided_page_range(
page.number, on_each_side=2, on_ends=1
),
}
last_week = timezone.now() - datetime.timedelta(days=7)
recent_avg = (
models.ImportJob.objects.filter(created_date__gte=last_week, complete=True)
.annotate(
runtime=ExpressionWrapper(
F("updated_date") - F("created_date"),
output_field=fields.DurationField(),
)
)
.aggregate(Avg("runtime"))
.get("runtime__avg")
)
if recent_avg:
seconds = recent_avg.total_seconds()
if seconds > 60**2:
data["recent_avg_hours"] = recent_avg.seconds / (60**2)
else:
data["recent_avg_minutes"] = recent_avg.seconds / 60
return TemplateResponse(request, "import/import.html", data)
def post(self, request):
"""ingest a goodreads csv"""