Full add author flow

This commit is contained in:
Mouse Reeve 2021-03-04 17:09:49 -08:00
parent b2d1384bc5
commit 5c089db086
5 changed files with 96 additions and 57 deletions

View file

@ -8,7 +8,7 @@
<header class="block">
<h1 class="title level-left">
{% if book %}
{% blocktrans with book_title=book.title %}Edit "{{ book.title }}"{% endblocktrans %}
{% blocktrans with book_title=book.title %}Edit "{{ book_title }}"{% endblocktrans %}
{% else %}
{% trans "Add Book" %}
{% endif %}
@ -26,9 +26,46 @@
</div>
{% endif %}
<form class="block" name="edit-book" action="{{ book.local_path }}/edit#deduplication" method="post" enctype="multipart/form-data">
<fieldset {% if confirm_mode %}disabled{% endif %}>
<form class="block" name="edit-book" action="{{ book.local_path }}/{% if confirm_mode %}confirm{% else %}edit{% endif %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% if confirm_mode %}
<div class="box">
<h2 class="title is-4">{% trans "Confirm Book Info" %}</h2>
<div class="columns">
{% if author_matches.exists %}
<fieldset class="column is-half">
<legend class="label">{% blocktrans with name=add_author %}Is "{{ name }}" an existing author?{% endblocktrans %}</legend>
{% for match in author_matches %}
<label><input type="radio" name="author_match" value="{{ match.id }}" required> {{ match.name }}</label>
<p class="help">
<a href="{{ author.local_path }}" target="_blank">{% blocktrans with book_title=match.book_set.first.title %}Author of <em>{{ book_title }}</em>{% endblocktrans %}</a>
</p>
{% endfor %}
<label><input type="radio" name="author_match"> {% trans "This is a new author" %}</label>
</fieldset>
{% else %}
<p class="column is-half">{% blocktrans with name=add_author %}Creating a new author: {{ name }}{% endblocktrans %}</p>
{% endif %}
{% if not book %}
<fieldset class="column is-half">
<legend class="title is-5">{% trans "Is this an editions of an existing work?" %}</legend>
{% for match in book_matches %}
<label class="label"><input type="radio" name="parent_work" value="{{ match.parent_work.id }}"> {{ match.parent_work.title }}</label>
{% endfor %}
<label><input type="radio" name="parent_work"> this is a new work</label>
</fieldset>
{% endif %}
</div>
<button class="button is-primary" type="submit">{% trans "Confirm" %}</button>
<button class="button" type="button">{% trans "Back" %}</button>
</div>
<hr class="block">
{% endif %}
<fieldset>
<input type="hidden" name="last_edited_by" value="{{ request.user.id }}">
<div class="columns">
<div class="column">
@ -72,8 +109,12 @@
<input type="checkbox" name="remove_author" value="{{ author.id }}"> {% trans "Remove this author" %}
</label>
{% endfor %}
{% if confirm_mode %}
<input type="hidden" name="add_author" id="id_add_author" value="{{ add_author }}">
{% else %}
<label class="label" for="id_add_author">{% trans "Add Author:" %}</label>
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="John Doe" value="{{ add_author }}">
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="{% trans 'John Doe' %}" value="{{ add_author }}">
{% endif %}
</section>
</div>
@ -142,39 +183,4 @@
</fieldset>
</form>
{% if author_matches or book_matches %}
<hr class="block">
<form class="box content" id="deduplication">
<h2 class="title is-4">{% trans "Confirm Book Info" %}</h2>
<div class="columns">
{% if author_matches.exists %}
<fieldset class="column is-half">
<legend class="label">{% blocktrans %}Is "{{ add_author }}" an existing author?{% endblocktrans %}</legend>
{% for match in author_matches %}
<label class="label"><input type="radio" name="author_match" value="{{ match.id }}"> {{ match.name }}</label>
<p class="help">
<a href="{{ author.local_path }}" target="_blank">{% blocktrans with book_title=match.book_set.first.title %}Author of <em>{{ book_title }}</em>{% endblocktrans %}</a>
</p>
{% endfor %}
<label class="label"><input type="radio" name="author_match"> this is a new author</label>
</fieldset>
{% else %}
<p class="column is-half">{% blocktrans %}Creating a new author: {{ add_author }}{% endblocktrans %}</p>
{% endif %}
{% if not book %}
<fieldset class="column is-half">
<legend class="title is-5">{% trans "Is this an editions of an existing work?" %}</legend>
{% for match in book_matches %}
<label class="label"><input type="radio" name="book_match" value="{{ match.id }}"> {{ match.title }}</label>
{% endfor %}
<label class="label"><input type="radio" name="book_match"> this is a new work</label>
</fieldset>
{% endif %}
</div>
<button class="button is-primary" type="submit">{% trans "save" %}</button>
</form>
{% endif %}
{% endblock %}

View file

@ -85,18 +85,7 @@ class BookViews(TestCase):
def test_edit_book_add_author(self):
''' lets a user edit a book '''
view = views.EditBook.as_view()
self.local_user.groups.add(self.group)
form = forms.EditionForm(instance=self.book)
form.data['title'] = 'New Title'
form.data['last_edited_by'] = self.local_user.id
form.data['add_author'] = "John Doe"
request = self.factory.post('', form.data)
request.user = self.local_user
with patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay'):
view(request, self.book.id)
self.book.refresh_from_db()
self.assertEqual(self.book.title, 'New Title')
# TODO
def test_switch_edition(self):

View file

@ -129,6 +129,7 @@ urlpatterns = [
# books
re_path(r'%s(.json)?/?$' % book_path, views.Book.as_view()),
re_path(r'%s/edit/?$' % book_path, views.EditBook.as_view()),
re_path(r'%s/confirm/?$' % book_path, views.ConfirmEditBook.as_view()),
re_path(r'%s/editions(.json)?/?$' % book_path, views.Editions.as_view()),
re_path(r'^upload-cover/(?P<book_id>\d+)/?$', views.upload_cover),
re_path(r'^add-description/(?P<book_id>\d+)/?$', views.add_description),

View file

@ -2,7 +2,7 @@
from .authentication import Login, Register, Logout
from .author import Author, EditAuthor
from .block import Block, unblock
from .books import Book, EditBook, Editions
from .books import Book, EditBook, ConfirmEditBook, Editions
from .books import upload_cover, add_description, switch_edition, resolve_book
from .error import not_found_page, server_error_page
from .federation import Federation

View file

@ -122,8 +122,8 @@ class EditBook(View):
def post(self, request, book_id=None):
''' edit a book cool '''
book = get_object_or_404(models.Edition, id=book_id) if book_id \
else None
# returns None if no match is found
book = models.Edition.objects.filter(id=book_id).first()
form = forms.EditionForm(request.POST, request.FILES, instance=book)
data = {
@ -134,9 +134,8 @@ class EditBook(View):
return TemplateResponse(request, 'edit_book.html', data)
add_author = request.POST.get('add_author')
if not book or add_author:
# creting a book or adding an author to a book needs another step
data['confirm_mode'] = True
# we're adding an author through a free text field
if add_author:
data['add_author'] = add_author
# check for existing authors
vector = SearchVector('name', weight='A') +\
@ -148,6 +147,8 @@ class EditBook(View):
rank=SearchRank(vector, add_author)
).filter(rank__gt=0.8).order_by('-rank')[:5]
# we're creating a new book
if not book:
# check if this is an edition of an existing work
author_text = book.author_text if book else add_author
data['book_matches'] = connector_manager.local_search(
@ -156,12 +157,54 @@ class EditBook(View):
raw=True
)[:5]
# either of the above cases requires additional confirmation
if add_author or not book:
# creting a book or adding an author to a book needs another step
data['confirm_mode'] = True
return TemplateResponse(request, 'edit_book.html', data)
book = form.save()
return redirect('/book/%s' % book.id)
@method_decorator(login_required, name='dispatch')
@method_decorator(
permission_required('bookwyrm.edit_book', raise_exception=True),
name='dispatch')
class ConfirmEditBook(View):
''' confirm edits to a book '''
def post(self, request, book_id=None):
''' edit a book cool '''
# returns None if no match is found
book = models.Edition.objects.filter(id=book_id).first()
form = forms.EditionForm(request.POST, request.FILES, instance=book)
data = {
'book': book,
'form': form
}
if not form.is_valid():
return TemplateResponse(request, 'edit_book.html', data)
# create work, if needed
# TODO
# save book
book = form.save()
# get or create author as needed
if request.POST.get('add_author'):
if request.POST.get('author_match'):
author = get_object_or_404(
models.Author, id=request.POST['author_match'])
else:
author = models.Author.objects.create(
name=request.POST.get('add_author'))
book.authors.add(author)
return redirect('/book/%s' % book.id)
class Editions(View):
''' list of editions '''
def get(self, request, book_id):