Allow import retry

This commit is contained in:
Mouse Reeve 2020-11-13 09:02:41 -08:00
parent 083b576bc4
commit e3a803b907
6 changed files with 103 additions and 15 deletions

View file

@ -1,6 +1,5 @@
''' handle reading a csv from goodreads ''' ''' handle reading a csv from goodreads '''
import csv import csv
from requests import HTTPError
from bookwyrm import outgoing from bookwyrm import outgoing
from bookwyrm.tasks import app from bookwyrm.tasks import app
@ -24,6 +23,17 @@ def create_job(user, csv_file, include_reviews, privacy):
ImportItem(job=job, index=index, data=entry).save() ImportItem(job=job, index=index, data=entry).save()
return job return job
def create_retry_job(user, original_job, items):
''' retry items that didn't import '''
job = ImportJob.objects.create(
user=user,
include_reviews=original_job.include_reviews,
privacy=original_job.privacy,
retry=True
)
for item in items:
ImportItem(job=job, index=item.index, data=item.data).save()
return job
def start_import(job): def start_import(job):
''' initalizes a csv import job ''' ''' initalizes a csv import job '''

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.7 on 2020-11-13 15:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bookwyrm', '0009_shelf_privacy'),
]
operations = [
migrations.AddField(
model_name='importjob',
name='retry',
field=models.BooleanField(default=False),
),
]

View file

@ -48,6 +48,7 @@ class ImportJob(models.Model):
default='public', default='public',
choices=PrivacyLevels.choices choices=PrivacyLevels.choices
) )
retry = models.BooleanField(default=False)
class ImportItem(models.Model): class ImportItem(models.Model):
@ -100,6 +101,16 @@ class ImportItem(models.Model):
return None return None
@property
def title(self):
''' get the book title '''
return self.data['Title']
@property
def author(self):
''' get the book title '''
return self.data['Author']
@property @property
def isbn(self): def isbn(self):
''' pulls out the isbn13 field from the csv line data ''' ''' pulls out the isbn13 field from the csv line data '''

View file

@ -29,16 +29,47 @@
{% if failed_items %} {% if failed_items %}
<div class="block"> <div class="block">
<h2 class="title is-4">Failed to load</h2> <h2 class="title is-4">Failed to load</h2>
<ul> {% if not job.retry %}
{% for item in failed_items %} <form name="retry" action="/retry-import/" method="post">
<li> {% csrf_token %}
Line {{ item.index }}: <input type="hidden" name="import_job" value="{{ job.id }}">
<strong>{{ item.data|dict_key:'Title' }}</strong> by <ul>
{{ item.data|dict_key:'Author' }} <fieldset>
({{ item.fail_reason }}) {% for item in failed_items %}
</li> <li class="pb-1">
{% endfor %} <input class="checkbox" type="checkbox" name="import_item" value="{{ item.id }}" id="import-item-{{ item.id }}">
</ul> <label for="import-item-{{ item.id }}">
Line {{ item.index }}:
<strong>{{ item.data|dict_key:'Title' }}</strong> by
{{ item.data|dict_key:'Author' }}
</label>
<p>
{{ item.fail_reason }}.
<a href="/create-book/{{ item.id }}">Manually add book</a>
</p>
</li>
{% endfor %}
</fieldset>
</ul>
<button class="button" type="submit">Retry items</button>
{% else %}
<ul>
{% for item in failed_items %}
<li class="pb-1">
<p>
Line {{ item.index }}:
<strong>{{ item.data|dict_key:'Title' }}</strong> by
{{ item.data|dict_key:'Author' }}
</p>
<p>
{{ item.fail_reason }}.
<a href="/create-book/{{ item.id }}">Manually add book</a>
</p>
</li>
{% endfor %}
</ul>
{% endif %}
</form>
</div> </div>
{% endif %} {% endif %}

View file

@ -54,9 +54,9 @@ urlpatterns = [
path('', views.home), path('', views.home),
re_path(r'^(?P<tab>home|local|federated)/?$', views.home_tab), re_path(r'^(?P<tab>home|local|federated)/?$', views.home_tab),
re_path(r'^notifications/?', views.notifications_page), re_path(r'^notifications/?', views.notifications_page),
re_path(r'import/?$', views.import_page), re_path(r'^import/?$', views.import_page),
re_path(r'import-status/(\d+)/?$', views.import_status), re_path(r'^import-status/(\d+)/?$', views.import_status),
re_path(r'user-edit/?$', views.edit_profile_page), re_path(r'^user-edit/?$', views.edit_profile_page),
# should return a ui view or activitypub json blob as requested # should return a ui view or activitypub json blob as requested
# users # users
@ -98,6 +98,7 @@ urlpatterns = [
re_path(r'^edit-profile/?$', actions.edit_profile), re_path(r'^edit-profile/?$', actions.edit_profile),
re_path(r'^import-data/?', actions.import_data), re_path(r'^import-data/?', actions.import_data),
re_path(r'^retry-import/?', actions.retry_import),
re_path(r'^resolve-book/?', actions.resolve_book), re_path(r'^resolve-book/?', actions.resolve_book),
re_path(r'^edit-book/(?P<book_id>\d+)/?', actions.edit_book), re_path(r'^edit-book/(?P<book_id>\d+)/?', actions.edit_book),
re_path(r'^upload-cover/(?P<book_id>\d+)/?', actions.upload_cover), re_path(r'^upload-cover/(?P<book_id>\d+)/?', actions.upload_cover),

View file

@ -662,10 +662,27 @@ def import_data(request):
except (UnicodeDecodeError, ValueError): except (UnicodeDecodeError, ValueError):
return HttpResponseBadRequest('Not a valid csv file') return HttpResponseBadRequest('Not a valid csv file')
goodreads_import.start_import(job) goodreads_import.start_import(job)
return redirect('/import-status/%d' % (job.id,)) return redirect('/import-status/%d' % job.id)
return HttpResponseBadRequest() return HttpResponseBadRequest()
@login_required
def retry_import(request):
''' ingest a goodreads csv '''
job = get_object_or_404(models.ImportJob, id=request.POST.get('import_job'))
items = []
for item in request.POST.getlist('import_item'):
items.append(get_object_or_404(models.ImportItem, id=item))
job = goodreads_import.create_retry_job(
request.user,
job,
items,
)
goodreads_import.start_import(job)
return redirect('/import-status/%d' % job.id)
@login_required @login_required
@permission_required('bookwyrm.create_invites', raise_exception=True) @permission_required('bookwyrm.create_invites', raise_exception=True)
def create_invite(request): def create_invite(request):