bookwyrm/bookwyrm/templates/book/book.html
Neil Roberts 603b2d9502 Show “no rating” instead of stars if the review has no rating
The stars.html template now outputs a span containing “no rating” when
the stars represent a non-existent or zero rating. This text is already
translated because it was previously added as a invisible text only for
screen readers. The span is given a special CSS class so that it can be
styled as italic in the stylesheet.

There is now also an extra span in book.html to group the stars with the
“(2 reviews)” text. This is needed because the outer div is using a flex
layout and it eats the spacing between the two parts otherwise.

Fixes #2856
2023-05-22 15:40:18 +02:00

430 lines
19 KiB
HTML

{% extends 'layout.html' %}
{% load i18n %}
{% load book_display_tags %}
{% load humanize %}
{% load utilities %}
{% load static %}
{% load shelf_tags %}
{% block title %}{{ book|book_title }}{% endblock %}
{% block opengraph %}
{% include 'snippets/opengraph.html' with title=book.title description=book|book_description image=book.preview_image %}
{% endblock %}
{% block content %}
{% if update_error %}
<div class="notification is-danger is-light">
<span class="icon icon-x" aria-hidden="true"></span>
<span>
{% trans "Unable to connect to remote source." %}
</span>
</div>
{% endif %}
{% with user_authenticated=request.user.is_authenticated can_edit_book=perms.bookwyrm.edit_book %}
<div class="block" itemscope itemtype="https://schema.org/Book">
<div class="columns is-mobile">
<div class="column">
<h1 class="title" itemprop="name" dir="auto">
{{ book.title }}
</h1>
{% if book.subtitle or book.series %}
<p class="subtitle title is-5">
{% if book.subtitle %}
<meta
itemprop="alternativeHeadline"
content="{{ book.subtitle | escape }}"
>
<span class="has-text-weight-bold" dir="auto">
{{ book.subtitle }}
</span>
{% endif %}
{% if book.series %}
<meta itemprop="isPartOf" content="{{ book.series | escape }}">
<meta itemprop="volumeNumber" content="{{ book.series_number }}">
{% if book.authors.exists %}
<a href="{% url 'book-series-by' book.authors.first.id %}?series_name={{ book.series }}">
{% endif %}
{{ book.series }}{% if book.series_number %} #{{ book.series_number }}{% endif %}
{% if book.authors.exists %}
</a>
{% endif %}
{% endif %}
</p>
{% endif %}
{% if book.authors.exists %}
<div class="subtitle" dir="auto">
{% trans "by" %} {% include 'snippets/authors.html' with book=book %}
</div>
{% endif %}
</div>
{% if user_authenticated and can_edit_book %}
<div class="column is-narrow">
<a href="{% url 'edit-book' book.id %}">
<span class="icon icon-pencil" title="{% trans "Edit Book" %}" aria-hidden=True></span>
<span class="is-hidden-mobile">{% trans "Edit Book" %}</span>
</a>
</div>
{% endif %}
</div>
<div class="columns">
<div class="column is-one-fifth">
{% if not book.cover %}
{% if user_authenticated %}
<button
type="button"
class="cover-container no-cover is-h-m-mobile"
data-modal-open="add_cover_{{ book.id }}"
>
<img
class="book-cover"
src="{% static "images/no_cover.jpg" %}"
alt=""
aria-hidden="true"
loading="lazy"
decoding="async"
>
<span class="cover-caption">
<span>{{ book.alt_text }}</span>
<span>{% trans "Click to add cover" %}</span>
</span>
<span class="button-invisible-overlay has-text-centered">
{% trans "Click to add cover" %}
</span>
</button>
{% join "add_cover" book.id as modal_id %}
{% include 'book/cover_add_modal.html' with id=modal_id %}
{% if request.GET.cover_error %}
<p class="help is-danger">{% trans "Failed to load cover" %}</p>
{% endif %}
{% else %}
{% include 'snippets/book_cover.html' with book=book cover_class='is-h-m-mobile' %}
{% endif %}
{% endif %}
{% if book.cover %}
<button type="button" data-modal-open="cover_show_modal" class="cover-container is-h-m-mobile is-relative">
{% include 'snippets/book_cover.html' with size='xxlarge' size_mobile='medium' book=book cover_class='is-h-m-mobile' %}
<span class="button-invisible-overlay has-text-centered">
{% trans "Click to enlarge" %}
</span>
</button>
{% include 'book/cover_show_modal.html' with book=book id="cover_show_modal" %}
{% endif %}
{% include 'snippets/rate_action.html' with user=request.user book=book %}
<div class="mb-3" id="tour-shelve-button">
{% include 'snippets/shelve_button/shelve_button.html' %}
</div>
<section class="is-clipped">
{% with book=book %}
<div class="content">
{% include 'book/publisher_info.html' %}
</div>
<div class="my-3">
{% include 'book/book_identifiers.html' %}
</div>
{% endwith %}
{% trans "Load data" as button_text %}
{% if book.openlibrary_key %}
<p>
<a href="{{ book.openlibrary_link }}" target="_blank" rel="nofollow noopener noreferrer">
{% trans "View on OpenLibrary" %}
</a>
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
<button class="button is-small button-paragraph" type="button" data-modal-open="openlibrary_sync">
<span class="icon icon-download" title="{{ button_text }}"></span>
<span class="is-sr-only-mobile">{{ button_text }}</span>
</button>
{% include "book/sync_modal.html" with source="openlibrary.org" source_name="OpenLibrary" id="openlibrary_sync" %}
{% endif %}
</p>
{% endif %}
{% if book.inventaire_id %}
<p>
<a href="{{ book.inventaire_link }}" target="_blank" rel="nofollow noopener noreferrer">
{% trans "View on Inventaire" %}
</a>
{% if request.user.is_authenticated and perms.bookwyrm.edit_book %}
<button class="button is-small button-paragraph" type="button" data-modal-open="inventaire_sync">
<span class="icon icon-download" title="{{ button_text }}"></span>
<span class="is-sr-only-mobile">{{ button_text }}</span>
</button>
{% include "book/sync_modal.html" with source="inventaire.io" source_name="Inventaire" id="inventaire_sync" %}
{% endif %}
</p>
{% endif %}
{% if book.isfdb %}
<p>
<a href="{{ book.isfdb_link }}" target="_blank" rel="nofollow noopener noreferrer">
{% trans "View on ISFDB" %}
</a>
</p>
{% endif %}
</section>
</div>
<div class="column is-three-fifths">
<div class="block">
<div
class="field is-grouped"
itemprop="aggregateRating"
itemscope
itemtype="https://schema.org/AggregateRating"
>
<meta itemprop="ratingValue" content="{{ rating|floatformat }}">
{# @todo Is it possible to not hard-code the value? #}
<meta itemprop="bestRating" content="5">
<meta itemprop="reviewCount" content="{{ review_count }}">
<span>
{% include 'snippets/stars.html' with rating=rating %}
{% blocktrans count counter=review_count trimmed %}
({{ review_count }} review)
{% plural %}
({{ review_count }} reviews)
{% endblocktrans %}
</span>
</div>
{% with full=book|book_description itemprop='abstract' %}
{% include 'snippets/trimmed_text.html' %}
{% endwith %}
{% if user_authenticated and can_edit_book and not book|book_description %}
{% trans 'Add Description' as button_text %}
{% include 'snippets/toggle/open_button.html' with class="mb-2" text=button_text controls_text="add_description" controls_uid=book.id focus="id_description" hide_active=True id="hide_description" %}
<div class="box is-hidden" id="add_description_{{ book.id }}">
<form name="add-description" method="POST" action="{% url "add-description" book.id %}">
{% csrf_token %}
<div class="field">
<label class="label" for="id_description_{{ book.id }}">{% trans "Description:" %}</label>
<textarea name="description" cols="None" rows="None" class="textarea" id="id_description_{{ book.id }}"></textarea>
</div>
<div class="field">
<button class="button is-primary" type="submit">{% trans "Save" %}</button>
{% trans "Cancel" as button_text %}
{% include 'snippets/toggle/close_button.html' with text=button_text controls_text="add_description" controls_uid=book.id hide_inactive=True %}
</div>
</form>
</div>
{% endif %}
{% with work=book.parent_work editions_count=book.parent_work.editions.count %}
<p>
<a href="{{ work.local_path }}/editions" id="tour-other-editions-link">
{% blocktrans trimmed count counter=editions_count with count=editions_count|intcomma %}
{{ count }} edition
{% plural %}
{{ count }} editions
{% endblocktrans %}
</a>
</p>
{% endwith %}
</div>
{# user's relationship to the book #}
<div class="block">
{% if user_shelfbooks.count > 0 %}
<h2 class="title is-5">
{% trans "You have shelved this edition in:" %}
</h2>
<ul>
{% for shelf in user_shelfbooks %}
<li class="box">
<a href="{{ shelf.shelf.local_path }}">{{ shelf.shelf|translate_shelf_name }}</a>
<div class="is-pulled-right">
{% include 'snippets/shelf_selector.html' with shelf=shelf.shelf class="is-small" readthrough=readthrough %}
</div>
</li>
{% endfor %}
</ul>
{% endif %}
{% for shelf in other_edition_shelves %}
<p>
{% blocktrans with book_path=shelf.book.local_path shelf_path=shelf.shelf.local_path shelf_name=shelf.shelf|translate_shelf_name %}A <a href="{{ book_path }}">different edition</a> of this book is on your <a href="{{ shelf_path }}">{{ shelf_name }}</a> shelf.{% endblocktrans %}
{% include 'snippets/switch_edition_button.html' with edition=book %}
</p>
{% endfor %}
</div>
{% if user_authenticated %}
<hr aria-hidden="true">
<section class="block">
<header class="columns">
<div class="column">
<h2 class="title is-5">{% trans "Your reading activity" %}</h2>
</div>
<div class="column is-narrow">
<button class="button is-small" data-modal-open="add-readthrough" id="tour-add-readthrough">
<span class="icon icon-plus m-mobile-0" aria-hidden="true"></span>
<span class="is-sr-only-mobile">
{% trans "Add read dates" %}
</span>
</button>
</div>
</header>
{% include "readthrough/readthrough_modal.html" with id="add-readthrough" %}
{% if not readthroughs.exists %}
<p>{% trans "You don't have any reading activity for this book." %}</p>
{% endif %}
{% for readthrough in readthroughs %}
{% include 'readthrough/readthrough_list.html' with readthrough=readthrough %}
{% endfor %}
</section>
<hr aria-hidden="true">
<section class="box">
{% with 0|uuid as controls_uid %}
{% include 'snippets/create_status.html' with book=book hide_cover=True %}
{% endwith %}
</section>
{% endif %}
<div class="block" id="reviews">
{% if request.user.is_authenticated %}
{% if user_statuses.review_count or user_statuses.comment_count or user_statuses.quotation_count %}
<nav class="tabs">
<ul>
{% url 'book' book.id book.name|slugify as tab_url %}
<li {% if tab_url == request.path %}class="is-active"{% endif %}>
<a href="{{ tab_url }}#reviews">{% 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 }}#reviews">{% 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 }}#reviews">{% 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 }}#reviews">{% trans "Your quotes" %} ({{ user_statuses.quotation_count }})</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% endif %}
{% for status in statuses %}
<div
class="block"
{% if status.status_type == 'Review' or status.status_type == 'Rating' %}
itemprop="review"
itemscope
itemtype="https://schema.org/Review"
{% endif %}
>
{% include 'snippets/status/status.html' with status=status hide_book=True depth=1 %}
</div>
{% endfor %}
{% if ratings %}
<div class="block is-flex is-flex-wrap-wrap">
{% for rating in ratings %}
{% include 'book/rating.html' with user=rating.user rating=rating %}
{% endfor %}
</div>
{% endif %}
<div class="block">
{% include 'snippets/pagination.html' with page=statuses path=request.path anchor="#reviews" %}
</div>
</div>
</div>
<div class="column is-one-fifth is-clipped">
{% if book.subjects %}
<section class="content block">
<h2 class="title is-5">{% trans "Subjects" %}</h2>
<ul>
{% for subject in book.subjects %}
<li itemprop="about">{{ subject }}</li>
{% endfor %}
</ul>
</section>
{% endif %}
{% if book.subject_places %}
<section class="content block">
<h2 class="title is-5">{% trans "Places" %}</h2>
<ul>
{% for place in book.subject_places %}
<li>{{ place }}</li>
{% endfor %}
</ul>
</section>
{% endif %}
{% if lists.exists or request.user.list_set.exists %}
<section class="content block is-clipped">
<h2 class="title is-5">{% trans "Lists" %}</h2>
<ul>
{% for list in lists %}
<li><a href="{{ list.local_path }}">{{ list.name }}</a></li>
{% endfor %}
</ul>
{% if list_options.exists %}
<form name="list-add" method="post" action="{% url 'list-add-book' %}">
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="user" value="{{ request.user.id }}">
<label class="label" for="id_list">{% trans "Add to list" %}</label>
<div class="field has-addons">
<div class="select control is-clipped">
<select name="book_list" id="id_list">
{% for list in list_options %}
<option value="{{ list.id }}">{{ list.name }}</option>
{% endfor %}
</select>
</div>
<div class="control">
<button type="submit" class="button is-link">{% trans "Add" %}</button>
</div>
</div>
</form>
{% endif %}
</section>
{% endif %}
<section class="content block" id="tour-book-file-links">
{% include "book/file_links/links.html" %}
</section>
</div>
</div>
</div>
{% endwith %}
{% endblock %}
{% block scripts %}
<script src="{% static "js/tabs.js" %}?v={{ js_cache }}"></script>
<script src="{% static "js/autocomplete.js" %}?v={{ js_cache }}"></script>
{% if request.user.show_guided_tour %}
{% include 'guided_tour/book.html' %}
{% endif %}
{% endblock %}