mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-12-23 08:36:32 +00:00
handle work/edition concepts in ui
This commit is contained in:
parent
f7fb9dde99
commit
defd026ed0
6 changed files with 69 additions and 28 deletions
|
@ -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 '''
|
||||||
|
|
|
@ -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' %}
|
||||||
|
|
||||||
|
|
18
fedireads/templates/editions.html
Normal file
18
fedireads/templates/editions.html
Normal 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 %}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue