Merge branch 'main' into frontend-book-cover

This commit is contained in:
Fabien Basmaison 2021-04-26 11:35:10 +02:00
commit 30bed6c963
17 changed files with 404 additions and 377 deletions

View file

@ -29,6 +29,40 @@ body {
min-width: 75% !important;
}
/** Utilities not covered by Bulma
******************************************************************************/
@media only screen and (max-width: 768px) {
.is-sr-only-mobile {
border: none !important;
clip: rect(0, 0, 0, 0) !important;
height: 0.01em !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
white-space: nowrap !important;
width: 0.01em !important;
}
.m-0-mobile {
margin: 0 !important;
}
}
.button.is-transparent {
background-color: transparent;
}
.card.is-stretchable {
display: flex;
flex-direction: column;
height: 100%;
}
.card.is-stretchable .card-content {
flex-grow: 1;
}
/** Shelving
******************************************************************************/
@ -257,3 +291,53 @@ body {
height: 150px;
}
}
/* Book preview table
******************************************************************************/
.book-preview td {
vertical-align: middle;
}
@media only screen and (max-width: 768px) {
table.is-mobile,
table.is-mobile tbody {
display: block;
}
table.is-mobile tr {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
border-top: 1px solid #dbdbdb;
}
table.is-mobile td {
display: block;
box-sizing: border-box;
flex: 1 0 100%;
order: 2;
border-bottom: 0;
}
table.is-mobile td.book-preview-top-row {
order: 1;
flex-basis: auto;
}
table.is-mobile td[data-title]:not(:empty)::before {
content: attr(data-title);
display: block;
font-size: 0.75em;
font-weight: bold;
}
table.is-mobile td:empty {
padding: 0;
}
table.is-mobile th,
table.is-mobile thead {
display: none;
}
}

View file

@ -245,7 +245,36 @@
</div>
<div class="block" id="reviews">
{% for review in reviews %}
{% if request.user.is_authenticated %}
<nav class="tabs">
<ul>
{% url 'book' book.id as tab_url %}
<li {% if tab_url == request.path %}class="is-active"{% endif %}>
<a href="{{ tab_url }}">{% trans "Reviews" %} ({{ review_count }})</a>
</li>
{% if user_statuses.review_count %}
{% url 'book-user-statuses' book.id 'review' as tab_url %}
<li {% if tab_url == request.path %}class="is-active"{% endif %}>
<a href="{{ tab_url }}">{% trans "Your reviews" %} ({{ user_statuses.review_count }})</a>
</li>
{% endif %}
{% if user_statuses.comment_count %}
{% url 'book-user-statuses' book.id 'comment' as tab_url %}
<li {% if tab_url == request.path %}class="is-active"{% endif %}>
<a href="{{ tab_url }}">{% trans "Your comments" %} ({{ user_statuses.comment_count }})</a>
</li>
{% endif %}
{% if user_statuses.quotation_count %}
{% url 'book-user-statuses' book.id 'quote' as tab_url %}
<li {% if tab_url == request.path %}class="is-active"{% endif %}>
<a href="{{ tab_url }}">{% trans "Your quotes" %} ({{ user_statuses.quotation_count }})</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% for review in statuses %}
<div
class="block"
itemprop="review"
@ -286,7 +315,7 @@
{% endfor %}
</div>
<div class="block">
{% include 'snippets/pagination.html' with page=reviews path=book.local_path anchor="#reviews" %}
{% include 'snippets/pagination.html' with page=statuses path=request.path anchor="#reviews" %}
</div>
</div>
</div>

View file

@ -41,7 +41,7 @@
<div class="columns is-multiline">
{% for user in users %}
<div class="column is-one-third">
<div class="card block">
<div class="card is-stretchable">
<div class="card-content">
<div class="media">
<a href="{{ user.local_path }}" class="media-left">
@ -56,13 +56,13 @@
</div>
</div>
<div class="content">
<div>
{% if user.summary %}
{{ user.summary | to_markdown | safe | truncatechars_html:40 }}
{% else %}&nbsp;{% endif %}
</div>
</div>
<footer class="card-footer content">
<footer class="card-footer">
{% if user != request.user %}
{% if user.mutuals %}
<div class="card-footer-item">

View file

@ -4,18 +4,16 @@
{% with status.id|uuid as uuid %}
<form name="boost" action="/boost/{{ status.id }}" method="post" class="interaction boost-{{ status.id }}-{{ uuid }} {% if request.user|boosted:status %}is-hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-small" type="submit" {% if not status.boostable %}disabled{% endif %}>
<span class="icon icon-boost" title="{% trans 'Boost status' %}">
<span class="is-sr-only">{% trans "Boost status" %}</span>
</span>
<button class="button is-small is-light is-transparent" type="submit" {% if not status.boostable %}disabled{% endif %}>
<span class="icon icon-boost m-0-mobile" title="{% trans 'Boost' %}"></span>
<span class="is-sr-only-mobile">{% trans "Boost" %}</span>
</button>
</form>
<form name="unboost" action="/unboost/{{ status.id }}" method="post" class="interaction boost-{{ status.id }}-{{ uuid }} active {% if not request.user|boosted:status %}is-hidden{% endif %}" data-id="boost-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-small is-primary" type="submit">
<span class="icon icon-boost" title="{% trans 'Un-boost status' %}">
<span class="is-sr-only">{% trans "Un-boost status" %}</span>
</span>
<button class="button is-small is-light is-transparent" type="submit">
<span class="icon icon-boost has-text-primary m-0-mobile" title="{% trans 'Un-boost' %}"></span>
<span class="is-sr-only-mobile">{% trans "Un-boost" %}</span>
</button>
</form>
{% endwith %}

View file

@ -3,18 +3,17 @@
{% with status.id|uuid as uuid %}
<form name="favorite" action="/favorite/{{ status.id }}" method="POST" class="interaction fav-{{ status.id }}-{{ uuid }} {% if request.user|liked:status %}is-hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-small" type="submit">
<span class="icon icon-heart" title="{% trans 'Like status' %}">
<span class="is-sr-only">{% trans "Like status" %}</span>
<button class="button is-small is-light is-transparent" type="submit">
<span class="icon icon-heart m-0-mobile" title="{% trans 'Like' %}">
</span>
<span class="is-sr-only-mobile">{% trans "Like" %}</span>
</button>
</form>
<form name="unfavorite" action="/unfavorite/{{ status.id }}" method="POST" class="interaction fav-{{ status.id }}-{{ uuid }} active {% if not request.user|liked:status %}is-hidden{% endif %}" data-id="fav-{{ status.id }}-{{ uuid }}">
{% csrf_token %}
<button class="button is-primary is-small" type="submit">
<span class="icon icon-heart" title="{% trans 'Un-like status' %}">
<span class="is-sr-only">{% trans "Un-like status" %}</span>
</span>
<button class="button is-light is-transparent is-small" type="submit">
<span class="icon icon-heart has-text-primary m-0-mobile" title="{% trans 'Un-like' %}"></span>
<span class="is-sr-only-mobile">{% trans "Un-like" %}</span>
</button>
</form>
{% endwith %}

View file

@ -14,11 +14,18 @@
{% if not hide_book %}
{% with book=status.book|default:status.mention_books.first %}
{% if book %}
<div class="column is-narrow is-hidden-mobile">
<div class="column is-narrow">
<div class="columns is-mobile">
<div class="column is-narrow">
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book %}</a>
{% include 'snippets/stars.html' with rating=book|rating:request.user %}
{% include 'snippets/shelve_button/shelve_button.html' with book=book %}
</div>
<div class="column is-hidden-tablet">
<p>{{ book|book_description|to_markdown|default:""|safe|truncatewords_html:15 }}</p>
</div>
</div>
</div>
{% endif %}
{% endwith %}
{% endif %}

View file

@ -4,16 +4,16 @@
{% load humanize %}
{% block card-header %}
<h3 class="card-header-title has-background-white-ter is-block">
<div class="card-header-title has-background-white-ter is-block">
{% include 'snippets/status/status_header.html' with status=status %}
</h3>
</div>
{% endblock %}
{% block card-content %}{% endblock %}
{% block card-footer %}
<div class="card-footer-item">
{% if moderation_mode and perms.bookwyrm.moderate_post %}
<div class="card-footer-item">
{# moderation options #}
<form name="delete-{{status.id}}" action="/delete-status/{{ status.id }}" method="post">
@ -22,54 +22,45 @@
{% trans "Delete status" %}
</button>
</form>
</div>
{% elif no_interact %}
{# nothing here #}
{% elif request.user.is_authenticated %}
<div class="field has-addons">
<div class="control">
<div class="card-footer-item">
{% trans "Reply" as button_text %}
{% include 'snippets/toggle/toggle_button.html' with controls_text="show-comment" controls_uid=status.id text=button_text icon="comment" class="is-small toggle-button" focus="id_content_reply" %}
{% include 'snippets/toggle/toggle_button.html' with controls_text="show-comment" controls_uid=status.id text=button_text icon_with_text="comment" class="is-small is-light is-transparent toggle-button" focus="id_content_reply" %}
</div>
<div class="control">
<div class="card-footer-item">
{% include 'snippets/boost_button.html' with status=status %}
</div>
<div class="control">
<div class="card-footer-item">
{% include 'snippets/fav_button.html' with status=status %}
</div>
</div>
{% else %}
<a href="/login">
<span class="icon icon-comment" title="{% trans 'Reply' %}">
<span class="is-sr-only">{% trans "Reply" %}</span>
</span>
<span class="icon icon-boost" title="{% trans 'Boost status' %}">
<span class="is-sr-only">{% trans "Boost status" %}</span>
</span>
<span class="icon icon-heart" title="{% trans 'Like status' %}">
<span class="is-sr-only">{% trans "Like status" %}</span>
</span>
</a>
{% endif %}
</div>
<div class="card-footer-item">
{% include 'snippets/privacy-icons.html' with item=status %}
</div>
<div class="card-footer-item">
<a href="{{ status.remote_id }}">{{ status.published_date|timesince }}</a>
</div>
{% if not moderation_mode %}
<div class="card-footer-item">
{% include 'snippets/status/status_options.html' with class="is-small" right=True %}
{% include 'snippets/status/status_options.html' with class="is-small is-light is-transparent" right=True %}
</div>
{% endif %}
{% else %}
<div class="card-footer-item">
<a href="/login">
<span class="icon icon-comment is-small" title="{% trans 'Reply' %}">
<span class="is-sr-only">{% trans "Reply" %}</span>
</span>
<span class="icon icon-boost is-small ml-4" title="{% trans 'Boost status' %}">
<span class="is-sr-only">{% trans "Boost status" %}</span>
</span>
<span class="icon icon-heart is-small ml-4" title="{% trans 'Like status' %}">
<span class="is-sr-only">{% trans "Like status" %}</span>
</span>
</a>
</div>
{% endif %}
{% endblock %}
{% block card-bonus %}
{% if request.user.is_authenticated and not moderation_mode %}
{% with status.id|uuid as uuid %}

View file

@ -1,134 +0,0 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% with status_type=status.status_type %}
<div
class="block"
{% if status_type == 'Review' %}
{% firstof "reviewBody" as body_prop %}
{% firstof 'itemprop="reviewRating" itemscope itemtype="https://schema.org/Rating"' as rating_type %}
{% endif %}
{% if status_type == 'Rating' %}
itemprop="rating"
itemtype="https://schema.org/Rating"
{% endif %}
>
{% if status_type == 'Review' or status_type == 'Rating' %}
<div>
{% if status.name %}
<h3
class="title is-5 has-subtitle"
dir="auto"
itemprop="name"
>
{{ status.name|escape }}
</h3>
{% endif %}
<span
class="is-sr-only"
{{ rating_type }}
>
<meta itemprop="ratingValue" content="{{ status.rating|floatformat }}">
{% if status_type == 'Rating' %}
{# @todo Is it possible to not hard-code the value? #}
<meta itemprop="bestRating" content="5">
{% endif %}
</span>
{% include 'snippets/stars.html' with rating=status.rating %}
</div>
{% endif %}
{% if status.content_warning %}
<div>
<p>{{ status.content_warning }}</p>
{% trans "Show more" as button_text %}
{% with text=button_text class="is-small" controls_text="show-status-cw" controls_uid=status.id %}
{% include 'snippets/toggle/open_button.html' %}
{% endwith %}
</div>
{% endif %}
<div
{% if status.content_warning %}
id="show-status-cw-{{ status.id }}"
class="is-hidden"
{% endif %}
>
{% if status.content_warning %}
{% trans "Show less" as button_text %}
{% with text=button_text class="is-small" controls_text="show-status-cw" controls_uid=status.id %}
{% include 'snippets/toggle/close_button.html' %}
{% endwith %}
{% endif %}
{% if status.quote %}
<div class="quote block">
<blockquote dir="auto" class="content mb-2">{{ status.quote | safe }}</blockquote>
<p> &mdash; {% include 'snippets/book_titleby.html' with book=status.book %}</p>
</div>
{% endif %}
{% if status.content and status_type != 'GeneratedNote' and status_type != 'Announce' %}
{% with full=status.content|safe no_trim=status.content_warning itemprop=body_prop %}
{% include 'snippets/trimmed_text.html' %}
{% endwith %}
{% endif %}
{% if status.attachments.exists %}
<div class="block">
<div class="columns">
{% for attachment in status.attachments.all %}
<div class="column is-narrow">
<figure class="image is-128x128">
<a
href="/images/{{ attachment.image }}"
target="_blank"
aria-label="{% trans 'Open image in new window' %}"
>
<img
src="/images/{{ attachment.image }}"
{% if attachment.caption %}
alt="{{ attachment.caption }}"
title="{{ attachment.caption }}"
{% endif %}
>
</a>
</figure>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>
{% if not hide_book %}
{% if status.book or status.mention_books.count %}
<div
{% if status_type != 'GeneratedNote' %}
class="box has-background-white-bis"
{% endif %}
>
{% if status.book %}
{% with book=status.book %}
{% include 'snippets/status/book_preview.html' %}
{% endwith %}
{% elif status.mention_books.count %}
{% with book=status.mention_books.first %}
{% include 'snippets/status/book_preview.html' %}
{% endwith %}
{% endif %}
</div>
{% endif %}
{% endif %}
{% endwith %}

View file

@ -1,16 +1,29 @@
{% load bookwyrm_tags %}
{% load i18n %}
{% load humanize %}
<div class="media">
<figure class="media-left" aria-hidden="true">
<a class="image is-48x48" href="{{ status.user.local_path }}">
{% include 'snippets/avatar.html' with user=status.user ariaHide="true" medium="true" %}
</a>
</figure>
<div class="media-content">
<h3 class="has-text-weight-bold">
<span
itemprop="author"
itemscope
itemtype="https://schema.org/Person"
>
{% if status.user.avatar %}
<meta itemprop="image" content="/images/{{ status.user.avatar }}">
{% endif %}
<a
href="{{ status.user.local_path }}"
itemprop="url"
>
{% include 'snippets/avatar.html' with user=status.user ariaHide="true" %}
<span itemprop="name">{{ status.user.display_name }}</span>
</a>
</span>
@ -28,19 +41,21 @@
{% elif status.reply_parent %}
{% with parent_status=status|parent %}
{% if parent_status.status_type == 'Review' %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">review</a>{% endblocktrans %}
{% elif parent_status.status_type == 'Comment' %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">comment</a>{% endblocktrans %}
{% elif parent_status.status_type == 'Quotation' %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">quote</a>{% endblocktrans %}
{% else %}
{% blocktrans with username=parent_status.user.display_name user_path=parent_status.user.local_path status_path=parent_status.local_path %}replied to <a href="{{ user_path }}">{{ username}}'s</a> <a href="{{ status_path }}">status</a>{% endblocktrans %}
{% endif %}
{% endwith %}
{% endif %}
{% if status.book %}
{% if status.status_type == 'GeneratedNote' or status.status_type == 'Rating' %}
<a href="/book/{{ status.book.id }}">{{ status.book|title }}</a>{% if status.status_type == 'Rating' %}:
<span
itemprop="reviewRating"
itemscope
itemtype="https://schema.org/Rating"
>
<span class="is-hidden" {{ rating_type }}>
<meta itemprop="ratingValue" content="{{ status.rating|floatformat }}">
{% if status.book %}
{% if status.status_type == 'GeneratedNote' or status.status_type == 'Rating' %}
<a href="/book/{{ status.book.id }}">{{ status.book|title }}</a>{% if status.status_type == 'Rating' %}:
@ -61,12 +76,33 @@
{% else %}
{% include 'snippets/book_titleby.html' with book=status.book %}
{% endif %}
{% elif status.mention_books %}
<a href="/book/{{ status.mention_books.first.id }}">
{{ status.mention_books.first.title }}
</a>
{% endif %}
{% include 'snippets/stars.html' with rating=status.rating %}
{% endif %}
{% else %}
{% include 'snippets/book_titleby.html' with book=status.book %}
{% endif %}
{% elif status.mention_books %}
<a href="/book/{{ status.mention_books.first.id }}">{{ status.mention_books.first|title }}</a>
{% endif %}
</h3>
<p class="is-size-7 is-flex is-align-items-center">
<a href="{{ status.remote_id }}">{{ status.published_date|timesince }}</a>
{% if status.progress %}
<p class="help">
({% if status.progress_mode == 'PG' %}{% include 'snippets/page_text.html' with page=status.progress total_pages=status.book.pages %}{% else %}{{ status.progress }}%{% endif %})
</p>
<span class="ml-1">
{% if status.progress_mode == 'PG' %}
({% include 'snippets/page_text.html' with page=status.progress total_pages=status.book.pages %})
{% else %}
({{ status.progress }}%)
{% endif %}
</span>
{% endif %}
{% include 'snippets/privacy-icons.html' with item=status %}
</p>
</div>
</div>

View file

@ -3,9 +3,8 @@
{% load bookwyrm_tags %}
{% block dropdown-trigger %}
<span class="icon icon-dots-three">
<span class="is-sr-only">{% trans "More options" %}</span>
</span>
<span class="icon icon-dots-three m-0-mobile"></span>
<span class="is-sr-only-mobile">{% trans "More options" %}</span>
{% endblock %}
{% block dropdown-list %}

View file

@ -10,9 +10,12 @@
>
{% if icon %}
<span class="icon icon-{{ icon }}" title="{{ text }}">
<span class="icon icon-{{ icon }} m-0-mobile" title="{{ text }}">
<span class="is-sr-only">{{ text }}</span>
</span>
{% elif icon_with_text %}
<span class="icon icon-{{ icon_with_text }} m-0-mobile" title="{{ text }}"></span>
<span class="is-sr-only-mobile">{{ text }}</span>
{% else %}
<span>{{ text }}</span>
{% endif %}

View file

@ -68,10 +68,9 @@
<div class="block">
<div>
{% if books|length > 0 %}
<div class="scroll-x">
<table class="table is-striped is-fullwidth">
<tr class="book-preview">
<table class="table is-striped is-fullwidth is-mobile">
<thead>
<tr>
<th>{% trans "Cover" %}</th>
<th>{% trans "Title" %}</th>
<th>{% trans "Author" %}</th>
@ -83,34 +82,37 @@
<th aria-hidden="true"></th>
{% endif %}
</tr>
</thead>
<tbody>
{% for book in books %}
{% spaceless %}
<tr class="book-preview">
<td>
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book cover_class='is-h-small' %}</a>
<td class="book-preview-top-row">
<a href="{{ book.local_path }}">{% include 'snippets/book_cover.html' with book=book size="small" %}</a>
</td>
<td>
<td data-title="{% trans "Title" %}">
<a href="{{ book.local_path }}">{{ book.title }}</a>
</td>
<td>
<td data-title="{% trans "Author" %}">
{% include 'snippets/authors.html' %}
</td>
<td>
<td data-title="{% trans "Shelved" %}">
{{ book.created_date | naturalday }}
</td>
{% latest_read_through book user as read_through %}
<td>
<td data-title="{% trans "Started" %}">
{{ read_through.start_date | naturalday |default_if_none:""}}
</td>
<td>
<td data-title="{% trans "Finished" %}">
{{ read_through.finish_date | naturalday |default_if_none:""}}
</td>
{% if ratings %}
<td>
<td data-title="{% trans "Rating" %}">
{% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %}
</td>
{% endif %}
{% if shelf.user == request.user %}
<td>
<td class="book-preview-top-row has-text-right">
{% with right=True %}
{% if not shelf.id %}
{% active_shelf book as current %}
@ -122,9 +124,10 @@
</td>
{% endif %}
</tr>
{% endspaceless %}
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p>{% trans "This shelf is empty." %}</p>
{% if shelf.id and shelf.editable %}

View file

@ -260,7 +260,12 @@ urlpatterns = [
re_path(r"^boost/(?P<status_id>\d+)/?$", views.Boost.as_view()),
re_path(r"^unboost/(?P<status_id>\d+)/?$", views.Unboost.as_view()),
# books
re_path(r"%s(.json)?/?$" % book_path, views.Book.as_view()),
re_path(r"%s(.json)?/?$" % book_path, views.Book.as_view(), name="book"),
re_path(
r"%s/(?P<user_statuses>review|comment|quote)/?$" % book_path,
views.Book.as_view(),
name="book-user-statuses",
),
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"^create-book/?$", views.EditBook.as_view()),

View file

@ -28,7 +28,7 @@ from .helpers import is_api_request, get_edition, privacy_filter
class Book(View):
""" a book! this is the stuff """
def get(self, request, book_id):
def get(self, request, book_id, user_statuses=False):
""" info about a book """
try:
book = models.Book.objects.select_subclasses().get(id=book_id)
@ -40,22 +40,39 @@ class Book(View):
if isinstance(book, models.Work):
book = book.get_default_edition()
if not book:
if not book or not book.parent_work:
return HttpResponseNotFound()
work = book.parent_work
if not work:
return HttpResponseNotFound()
# all reviews for the book
reviews = models.Review.objects.filter(book__in=work.editions.all())
reviews = privacy_filter(request.user, reviews)
reviews = privacy_filter(
request.user, models.Review.objects.filter(book__in=work.editions.all())
)
# the reviews to show
paginated = Paginator(
reviews.exclude(Q(content__isnull=True) | Q(content="")), PAGE_LENGTH
)
reviews_page = paginated.get_page(request.GET.get("page"))
if user_statuses and request.user.is_authenticated:
if user_statuses == "review":
queryset = book.review_set
elif user_statuses == "comment":
queryset = book.comment_set
else:
queryset = book.quotation_set
queryset = queryset.filter(user=request.user)
else:
queryset = reviews.exclude(Q(content__isnull=True) | Q(content=""))
paginated = Paginator(queryset, PAGE_LENGTH)
data = {
"book": book,
"statuses": paginated.get_page(request.GET.get("page")),
"review_count": reviews.count(),
"ratings": reviews.filter(Q(content__isnull=True) | Q(content="")),
"rating": reviews.aggregate(Avg("rating"))["rating__avg"],
"lists": privacy_filter(
request.user, book.list_set.filter(listitem__approved=True)
),
}
if request.user.is_authenticated:
readthroughs = models.ReadThrough.objects.filter(
@ -67,29 +84,24 @@ class Book(View):
readthrough.progress_updates = (
readthrough.progressupdate_set.all().order_by("-updated_date")
)
data["readthroughs"] = readthroughs
user_shelves = models.ShelfBook.objects.filter(user=request.user, book=book)
data["user_shelves"] = models.ShelfBook.objects.filter(
user=request.user, book=book
)
other_edition_shelves = models.ShelfBook.objects.filter(
data["other_edition_shelves"] = models.ShelfBook.objects.filter(
~Q(book=book),
user=request.user,
book__parent_work=book.parent_work,
)
data = {
"book": book,
"reviews": reviews_page,
"review_count": reviews.count(),
"ratings": reviews.filter(Q(content__isnull=True) | Q(content="")),
"rating": reviews.aggregate(Avg("rating"))["rating__avg"],
"lists": privacy_filter(
request.user, book.list_set.filter(listitem__approved=True)
),
"user_shelves": user_shelves,
"other_edition_shelves": other_edition_shelves,
"readthroughs": readthroughs,
"path": "/book/%s" % book_id,
data["user_statuses"] = {
"review_count": book.review_set.filter(user=request.user).count(),
"comment_count": book.comment_set.filter(user=request.user).count(),
"quotation_count": book.quotation_set.filter(user=request.user).count(),
}
return TemplateResponse(request, "book/book.html", data)

1
fr-dev
View file

@ -1 +0,0 @@
bw-dev

Binary file not shown.

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-04-22 15:55+0000\n"
"POT-Creation-Date: 2021-04-25 04:01+0000\n"
"PO-Revision-Date: 2021-03-19 11:49+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,57 +18,57 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: bookwyrm/forms.py:232
#: bookwyrm/forms.py:224
msgid "A user with this email already exists."
msgstr "Ya existe un usuario con ese correo electrónico."
#: bookwyrm/forms.py:246
#: bookwyrm/forms.py:238
msgid "One Day"
msgstr "Un día"
#: bookwyrm/forms.py:247
#: bookwyrm/forms.py:239
msgid "One Week"
msgstr "Una semana"
#: bookwyrm/forms.py:248
#: bookwyrm/forms.py:240
msgid "One Month"
msgstr "Un mes"
#: bookwyrm/forms.py:249
#: bookwyrm/forms.py:241
msgid "Does Not Expire"
msgstr "Nunca se vence"
#: bookwyrm/forms.py:254
#: bookwyrm/forms.py:246
#, python-format
msgid "%(count)d uses"
msgstr "%(count)d usos"
#: bookwyrm/forms.py:257
#: bookwyrm/forms.py:249
msgid "Unlimited"
msgstr "Sin límite"
#: bookwyrm/forms.py:301
#: bookwyrm/forms.py:293
msgid "List Order"
msgstr "Orden de la lista"
#: bookwyrm/forms.py:302
#: bookwyrm/forms.py:294
msgid "Book Title"
msgstr "Título"
#: bookwyrm/forms.py:303 bookwyrm/templates/snippets/create_status_form.html:31
#: bookwyrm/forms.py:295 bookwyrm/templates/snippets/create_status_form.html:31
#: bookwyrm/templates/user/shelf.html:81
msgid "Rating"
msgstr "Calificación"
#: bookwyrm/forms.py:305 bookwyrm/templates/lists/list.html:72
#: bookwyrm/forms.py:297 bookwyrm/templates/lists/list.html:72
msgid "Sort By"
msgstr "Ordenar por"
#: bookwyrm/forms.py:309
#: bookwyrm/forms.py:301
msgid "Ascending"
msgstr "Ascendente"
#: bookwyrm/forms.py:310
#: bookwyrm/forms.py:302
msgid "Descending"
msgstr "Descendente"
@ -2047,7 +2047,7 @@ msgstr "Texto de registración cerrada:"
msgid "No cover"
msgstr "Sin portada"
#: bookwyrm/templates/snippets/book_titleby.html:3
#: bookwyrm/templates/snippets/book_titleby.html:4
#, python-format
msgid "<a href=\"%(path)s\">%(title)s</a> by "
msgstr "<a href=\"%(path)s\">%(title)s</a> por "
@ -2527,19 +2527,6 @@ msgstr "En orden ascendente"
msgid "Sorted descending"
msgstr "En orden descendente"
#: bookwyrm/templates/snippets/tag.html:14
msgid "Remove tag"
msgstr "Eliminar etiqueta"
#: bookwyrm/templates/snippets/tag.html:18
msgid "Add tag"
msgstr "Agregar etiqueta"
#: bookwyrm/templates/tag.html:9
#, python-format
msgid "Books tagged \"%(tag.name)s\""
msgstr "Libros etiquetados con \"%(tag.name)s\""
#: bookwyrm/templates/user/books_header.html:5
#, python-format
msgid "%(username)s's books"
@ -2754,6 +2741,15 @@ msgstr "No se pudo encontrar un usuario con esa dirección de correo electrónic
msgid "A password reset link sent to %s"
msgstr "Un enlace para reestablecer tu contraseña se enviará a %s"
#~ msgid "Remove tag"
#~ msgstr "Eliminar etiqueta"
#~ msgid "Add tag"
#~ msgstr "Agregar etiqueta"
#~ msgid "Books tagged \"%(tag.name)s\""
#~ msgstr "Libros etiquetados con \"%(tag.name)s\""
#~ msgid "Deactivate user"
#~ msgstr "Desactivar usuario"