handle work/edition concepts in ui

This commit is contained in:
Mouse Reeve 2020-03-30 15:03:21 -07:00
parent f7fb9dde99
commit defd026ed0
6 changed files with 69 additions and 28 deletions

View file

@ -91,7 +91,7 @@ class Book(FedireadsModel):
''' constructs the absolute reference to any db object ''' ''' constructs the absolute reference to any db object '''
base_path = 'https://%s' % DOMAIN base_path = 'https://%s' % DOMAIN
model_name = type(self).__name__.lower() model_name = type(self).__name__.lower()
return '%s/%s/%s' % (base_path, model_name, self.openlibrary_key) return '%s/book/%s' % (base_path, self.openlibrary_key)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
''' can't be abstract for query reasons, but you shouldn't USE it ''' ''' can't be abstract for query reasons, but you shouldn't USE it '''
@ -112,6 +112,13 @@ class Work(Book):
# library of congress catalog control number # library of congress catalog control number
lccn = models.CharField(max_length=255, blank=True, null=True) lccn = models.CharField(max_length=255, blank=True, null=True)
@property
def default_edition(self):
ed = Edition.objects.filter(parent_work=self, default=True).first()
if not ed:
ed = Edition.objects.filter(parent_work=self).first()
return ed
class Edition(Book): class Edition(Book):
''' an edition of a book ''' ''' an edition of a book '''

View file

@ -14,13 +14,12 @@
{% endif %} {% endif %}
</h2> </h2>
<div> <div>
{% if book.parent_work %}<p>Edition of <a href="/book/{{ book.parent_work.fedireads_key }}">{{ book.parent_work.title }}</a></p>{% endif %}
<div class="book-preview"> <div class="book-preview">
{% include 'snippets/book_cover.html' with book=book size=large %} {% include 'snippets/book_cover.html' with book=book size=large %}
<p>{{ active_tab }} rating: {{ rating | stars }}</p> <p>{{ active_tab }} rating: {{ rating | stars }}</p>
{% if book.description %} {% if book.parent_work.description %}
<blockquote>{{ book.description | description }}</blockquote> <blockquote>{{ book.parent_work.description | description }}</blockquote>
{% endif %} {% endif %}
<div> <div>
<div id="tag-cloud"> <div id="tag-cloud">
@ -29,6 +28,7 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<p><a href="/editions/{{ book.parent_work.id }}">{{ book.parent_work.edition_set.count }} other editions</a></p>
{% include 'snippets/shelve_button.html' %} {% include 'snippets/shelve_button.html' %}

View file

@ -0,0 +1,18 @@
{% extends 'layout.html' %}
{% load fr_display %}
{% block content %}
<div class="content-container">
<h2>Editions of <a href="/book/{{ work.fedireads_key }}">"{{ work.title }}"</a></h2>
<div class="book-grid row wrap">
{% for book in editions %}
<div class="book-preview">
<a href="{{ book.absolute_id }}">
{% include 'snippets/book_cover.html' with book=book %}
</a>
{% include 'snippets/shelve_button.html' with book=book %}
</div>
{% endfor %}
</div>
</div>
{% endblock %}

View file

@ -60,6 +60,7 @@ urlpatterns = [
re_path(r'%s(.json)?/?$' % book_path, views.book_page), re_path(r'%s(.json)?/?$' % book_path, views.book_page),
re_path(r'%s/(?P<tab>friends|local|federated)?$' % book_path, views.book_page), re_path(r'%s/(?P<tab>friends|local|federated)?$' % book_path, views.book_page),
re_path(r'%s/edit/?$' % book_path, views.edit_book_page), re_path(r'%s/edit/?$' % book_path, views.edit_book_page),
re_path(r'^editions/(?P<work_id>\d+)/?$', views.editions_page),
re_path(r'^author/(?P<author_identifier>[\w\-]+)/?$', views.author_page), re_path(r'^author/(?P<author_identifier>[\w\-]+)/?$', views.author_page),
re_path(r'^tag/(?P<tag_id>.+)/?$', views.tag_page), re_path(r'^tag/(?P<tag_id>.+)/?$', views.tag_page),

View file

@ -135,7 +135,10 @@ def upload_cover(request, book_id):
@login_required @login_required
def shelve(request): def shelve(request):
''' put a on a user's shelf ''' ''' put a on a user's shelf '''
book = models.Book.objects.get(id=request.POST['book']) book = models.Book.objects.select_subclasses().get(id=request.POST['book'])
if isinstance(book, models.Work):
book = book.default_edition
desired_shelf = models.Shelf.objects.filter( desired_shelf = models.Shelf.objects.filter(
identifier=request.POST['shelf'], identifier=request.POST['shelf'],
user=request.user user=request.user
@ -144,8 +147,8 @@ def shelve(request):
if request.POST.get('reshelve', True): if request.POST.get('reshelve', True):
try: try:
current_shelf = models.Shelf.objects.get( current_shelf = models.Shelf.objects.get(
user=request.user, shelf__user=request.user,
book=book edition=book
) )
outgoing.handle_unshelve(request.user, book, current_shelf) outgoing.handle_unshelve(request.user, book, current_shelf)
except models.Shelf.DoesNotExist: except models.Shelf.DoesNotExist:

View file

@ -52,15 +52,18 @@ def home_tab(request, tab):
size = sum(len(s['books']) for s in shelves) size = sum(len(s['books']) for s in shelves)
# books new to the instance, for discovery # books new to the instance, for discovery
if size < 6: if size < 6:
recent_books = models.Work.objects.order_by(
'-created_date'
)[:6 - size]
recent_books = [b.default_edition for b in recent_books]
shelves.append({ shelves.append({
'name': 'Recently added', 'name': 'Recently added',
'identifier': None, 'identifier': None,
'books': models.Edition.objects.order_by( 'books': recent_books,
'-created_date'
)[:6 - size],
'count': 6 - size, 'count': 6 - size,
}) })
# allows us to check if a user has shelved a book # allows us to check if a user has shelved a book
user_books = models.Edition.objects.filter(shelves__user=request.user).all() user_books = models.Edition.objects.filter(shelves__user=request.user).all()
@ -107,18 +110,21 @@ def home_tab(request, tab):
def books_page(request): def books_page(request):
''' discover books ''' ''' discover books '''
recent_books = models.Book.objects recent_books = models.Work.objects
if request.user.is_authenticated:
recent_books = recent_books.filter(
~Q(shelfbook__shelf__user=request.user)
)
recent_books = recent_books.order_by('-created_date')[:50] recent_books = recent_books.order_by('-created_date')[:50]
recent_books = [b.default_edition for b in recent_books]
if request.user.is_authenticated:
recent_books = models.Edition.objects.filter(
~Q(shelfbook__shelf__user=request.user),
id__in=[b.id for b in recent_books],
)
data = { data = {
'books': recent_books, 'books': recent_books,
} }
return TemplateResponse(request, 'books.html', data) return TemplateResponse(request, 'books.html', data)
@login_required @login_required
def import_page(request): def import_page(request):
''' import history from goodreads ''' ''' import history from goodreads '''
@ -322,16 +328,11 @@ def book_page(request, book_identifier, tab='friends'):
return JsonResponse(activitypub.get_book(book)) return JsonResponse(activitypub.get_book(book))
if isinstance(book, models.Work): if isinstance(book, models.Work):
book = models.Edition.objects.filter( book = book.default_edition
parent_work=book,
default=True
).first()
if not book:
book = models.Edition.objects.filter(
parent_work=book,
).first()
book_reviews = models.Review.objects.filter(book=book) work = book.parent_work
book_reviews = models.Review.objects.filter(book__in=work.edition_set.all())
if request.user.is_authenticated: if request.user.is_authenticated:
user_reviews = book_reviews.filter( user_reviews = book_reviews.filter(
@ -360,7 +361,7 @@ def book_page(request, book_identifier, tab='friends'):
# TODO: books can be on multiple shelves # TODO: books can be on multiple shelves
shelf = models.Shelf.objects.filter( shelf = models.Shelf.objects.filter(
user=request.user, user=request.user,
book=book edition=book
).first() ).first()
except models.Shelf.DoesNotExist: except models.Shelf.DoesNotExist:
shelf = None shelf = None
@ -422,6 +423,17 @@ def edit_book_page(request, book_identifier):
return TemplateResponse(request, 'edit_book.html', data) return TemplateResponse(request, 'edit_book.html', data)
def editions_page(request, work_id):
''' list of editions of a book '''
work = models.Work.objects.get(id=work_id)
editions = models.Edition.objects.filter(parent_work=work).all()
data = {
'editions': editions,
'work': work,
}
return TemplateResponse(request, 'editions.html', data)
def author_page(request, author_identifier): def author_page(request, author_identifier):
''' landing page for an author ''' ''' landing page for an author '''
try: try:
@ -429,10 +441,10 @@ def author_page(request, author_identifier):
except ValueError: except ValueError:
return HttpResponseNotFound() return HttpResponseNotFound()
books = models.Book.objects.filter(authors=author) books = models.Work.objects.filter(authors=author)
data = { data = {
'author': author, 'author': author,
'books': books, 'books': [b.default_edition for b in books],
} }
return TemplateResponse(request, 'author.html', data) return TemplateResponse(request, 'author.html', data)
@ -440,7 +452,7 @@ def author_page(request, author_identifier):
def tag_page(request, tag_id): def tag_page(request, tag_id):
''' books related to a tag ''' ''' books related to a tag '''
tag_obj = models.Tag.objects.filter(identifier=tag_id).first() tag_obj = models.Tag.objects.filter(identifier=tag_id).first()
books = models.Book.objects.filter(tag__identifier=tag_id).distinct() books = models.Edition.objects.filter(tag__identifier=tag_id).distinct()
data = { data = {
'books': books, 'books': books,
'tag': tag_obj, 'tag': tag_obj,