Merge pull request #1608 from hughrun/move-shelves

refactor shelf activity on book page
This commit is contained in:
Mouse Reeve 2021-12-02 12:06:07 -08:00 committed by GitHub
commit baca5e50e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 116 additions and 22 deletions

View file

@ -187,6 +187,7 @@ let StatusCache = new class {
.forEach(item => BookWyrm.addRemoveClass(item, "is-hidden", false)); .forEach(item => BookWyrm.addRemoveClass(item, "is-hidden", false));
// Remove existing disabled states // Remove existing disabled states
button.querySelectorAll("[data-shelf-dropdown-identifier] button") button.querySelectorAll("[data-shelf-dropdown-identifier] button")
.forEach(item => item.disabled = false); .forEach(item => item.disabled = false);

View file

@ -153,12 +153,21 @@
{# user's relationship to the book #} {# user's relationship to the book #}
<div class="block"> <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 %} {% for shelf in user_shelfbooks %}
<p> <li class="box">
{% blocktrans with path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}This edition is on your <a href="{{ path }}">{{ shelf_name }}</a> shelf.{% endblocktrans %} {% blocktrans with path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}<a href="{{ path }}">{{ shelf_name }}</a>{% endblocktrans %}
{% include 'snippets/shelf_selector.html' with current=shelf.shelf %} <div class="mb-3">
</p> {% include 'snippets/shelf_selector.html' with shelf=shelf.shelf class="is-small" readthrough=readthrough %}
</div>
</li>
{% endfor %} {% endfor %}
</ul>
{% endif %}
{% for shelf in other_edition_shelves %} {% for shelf in other_edition_shelves %}
<p> <p>
{% blocktrans with book_path=shelf.book.local_path shelf_path=shelf.shelf.local_path shelf_name=shelf.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 %} {% blocktrans with book_path=shelf.book.local_path shelf_path=shelf.shelf.local_path shelf_name=shelf.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 %}

View file

@ -9,10 +9,11 @@ Finish "<em>{{ book_title }}</em>"
{% endblock %} {% endblock %}
{% block modal-form-open %} {% block modal-form-open %}
<form name="finish-reading" action="{% url 'reading-status' 'finish' book.id %}" method="post" class="submit-status"> <form name="finish-reading" action="{% url 'reading-status' 'finish' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="id" value="{{ readthrough.id }}"> <input type="hidden" name="id" value="{{ readthrough.id }}">
<input type="hidden" name="reading_status" value="read"> <input type="hidden" name="reading_status" value="read">
<input type="hidden" name="shelf" value="{{ move_from }}">
{% endblock %} {% endblock %}
{% block reading-dates %} {% block reading-dates %}

View file

@ -9,8 +9,9 @@ Start "<em>{{ book_title }}</em>"
{% endblock %} {% endblock %}
{% block modal-form-open %} {% block modal-form-open %}
<form name="start-reading" action="{% url 'reading-status' 'start' book.id %}" method="post" class="submit-status"> <form name="start-reading" action="{% url 'reading-status' 'start' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
<input type="hidden" name="reading_status" value="reading"> <input type="hidden" name="reading_status" value="reading">
<input type="hidden" name="shelf" value="{{ move_from }}">
{% csrf_token %} {% csrf_token %}
{% endblock %} {% endblock %}

View file

@ -9,8 +9,9 @@ Want to Read "<em>{{ book_title }}</em>"
{% endblock %} {% endblock %}
{% block modal-form-open %} {% block modal-form-open %}
<form name="shelve" action="{% url 'reading-status' 'want' book.id %}" method="post" class="submit-status"> <form name="shelve" action="{% url 'reading-status' 'want' book.id %}" method="post" {% if not refresh %}class="submit-status"{% endif %}>
<input type="hidden" name="reading_status" value="to-read"> <input type="hidden" name="reading_status" value="to-read">
<input type="hidden" name="shelf" value="{{ move_from }}">
{% csrf_token %} {% csrf_token %}
{% endblock %} {% endblock %}

View file

@ -1,29 +1,88 @@
{% extends 'components/dropdown.html' %} {% extends 'components/dropdown.html' %}
{% load i18n %} {% load i18n %}
{% load bookwyrm_tags %}
{% load utilities %}
{% block dropdown-trigger %} {% block dropdown-trigger %}
<span>{% trans "Move book" %}</span> <span>{% trans "Move book" %}</span>
<span class="icon icon-arrow-down" aria-hidden="true"></span> <span class="icon icon-arrow-down" aria-hidden="true"></span>
{% endblock %} {% endblock %}
{% block dropdown-list %} {% block dropdown-list %}
{% with book.id|uuid as uuid %}
{% active_shelf book as active_shelf %}
{% latest_read_through book request.user as readthrough %}
{% for shelf in user_shelves %} {% for shelf in user_shelves %}
{% if shelf.editable %}
<li role="menuitem" class="dropdown-item p-0"> <li role="menuitem" class="dropdown-item p-0">
<form name="shelve" action="/shelve/" method="post"> <form name="shelve" action="/shelve/" method="post">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}"> <input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="change-shelf-from" value="{{ current.identifier }}"> <input type="hidden" name="change-shelf-from" value="{{ current.identifier }}">
<input type="hidden" name="shelf" value="{{ shelf.identifier }}"> <input type="hidden" name="shelf" value="{{ shelf.identifier }}">
<button class="button is-fullwidth is-small shelf-option is-radiusless is-white" type="submit" {% if shelf.identifier == current.identifier %}disabled{% endif %}><span>{{ shelf.name }}</span></button> <button class="button is-fullwidth is-small shelf-option is-radiusless is-white" type="submit" {% if shelf in book.shelf_set.all %} disabled {% endif %}><span>{{ shelf.name }}</span></button>
</form> </form>
</li> </li>
{% else%}
{% comparison_bool shelf.identifier active_shelf.shelf.identifier as is_current %}
{% with button_class="is-fullwidth is-small shelf-option is-radiusless is-white" %}
<li role="menuitem" class="dropdown-item p-0">
{% if shelf.identifier == 'reading' %}
{% trans "Start reading" as button_text %}
{% url 'reading-status' 'start' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=button_class text=button_text controls_text="start_reading" controls_uid=uuid focus="modal_title_start_reading" disabled=is_current fallback_url=fallback_url %}
{% elif shelf.identifier == 'read' %}
{% trans "Read" as button_text %}
{% url 'reading-status' 'finish' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=button_class text=button_text controls_text="finish_reading" controls_uid=uuid focus="modal_title_finish_reading" disabled=is_current fallback_url=fallback_url %}
{% elif shelf.identifier == 'to-read' %}
{% trans "Want to read" as button_text %}
{% url 'reading-status' 'want' book.id as fallback_url %}
{% include 'snippets/toggle/toggle_button.html' with class=button_class text=button_text controls_text="want_to_read" controls_uid=uuid focus="modal_title_want_to_read" disabled=is_current fallback_url=fallback_url %}
{% endif %}
</li>
{% endwith %}
{% endif %}
{% endfor %} {% endfor %}
<li class="navbar-divider" role="separator"></li>
{% if shelf.identifier == 'all' %}
{% for shelved_in in book.shelves.all %}
<li class="navbar-divider m-0" role="separator" ></li>
<li role="menuitem" class="dropdown-item p-0"> <li role="menuitem" class="dropdown-item p-0">
<form name="shelve" action="/unshelve/" method="post"> <form name="shelve" action="/unshelve/" method="post">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}"> <input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="shelf" value="{{ current.id }}"> <input type="hidden" name="shelf" value="{{ shelved_in.id }}">
<button class="button is-fullwidth is-small is-radiusless is-danger is-light" type="submit">{% trans "Remove" %}</button> <button class="button is-fullwidth is-small is-radiusless is-danger is-light" type="submit">{% trans "Remove from" %} {{ shelved_in.name }}</button>
</form> </form>
</li> </li>
{% endfor %}
{% else %}
<li class="navbar-divider" role="separator" ></li>
<li role="menuitem" class="dropdown-item p-0">
<form name="shelve" action="/unshelve/" method="post">
{% csrf_token %}
<input type="hidden" name="book" value="{{ book.id }}">
<input type="hidden" name="shelf" value="{{ shelf.id }}">
<button class="button is-fullwidth is-small is-radiusless is-danger is-light" type="submit">{% trans "Remove from" %} {{ shelf.name }}</button>
</form>
</li>
{% endif %}
{% include 'snippets/reading_modals/want_to_read_modal.html' with book=active_shelf.book controls_text="want_to_read" controls_uid=uuid move_from=current.id refresh=True %}
{% include 'snippets/reading_modals/start_reading_modal.html' with book=active_shelf.book controls_text="start_reading" controls_uid=uuid move_from=current.id refresh=True %}
{% include 'snippets/reading_modals/finish_reading_modal.html' with book=active_shelf.book controls_text="finish_reading" controls_uid=uuid move_from=current.id readthrough=readthrough refresh=True %}
{% endwith %}
{% endblock %} {% endblock %}

View file

@ -32,7 +32,7 @@
{% elif shelf.editable %} {% elif shelf.editable %}
<form name="shelve" action="/shelve/" method="post"> <form name="shelve" action="/shelve/" method="post" autocomplete="off">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="book" value="{{ active_shelf.book.id }}"> <input type="hidden" name="book" value="{{ active_shelf.book.id }}">
<button class="button {{ class }}" name="shelf" type="submit" value="{{ shelf.identifier }}" {% if shelf in book.shelf_set.all %} disabled {% endif %}> <button class="button {{ class }}" name="shelf" type="submit" value="{{ shelf.identifier }}" {% if shelf in book.shelf_set.all %} disabled {% endif %}>

View file

@ -1,6 +1,6 @@
{% load utilities %} {% load utilities %}
{% if fallback_url %} {% if fallback_url %}
<form name="fallback_form_{{ 0|uuid }}" method="GET" action="{{ fallback_url }}"> <form name="fallback_form_{{ 0|uuid }}" method="GET" action="{{ fallback_url }}" autocomplete="off">
{% endif %} {% endif %}
<button <button
{% if not fallback_url %} {% if not fallback_url %}

View file

@ -77,7 +77,12 @@ def related_status(notification):
def active_shelf(context, book): def active_shelf(context, book):
"""check what shelf a user has a book on, if any""" """check what shelf a user has a book on, if any"""
if hasattr(book, "current_shelves"): if hasattr(book, "current_shelves"):
return book.current_shelves[0] if len(book.current_shelves) else {"book": book} read_shelves = [
s
for s in book.current_shelves
if s.shelf.identifier in models.Shelf.READ_STATUS_IDENTIFIERS
]
return read_shelves[0] if len(read_shelves) else {"book": book}
shelf = ( shelf = (
models.ShelfBook.objects.filter( models.ShelfBook.objects.filter(

View file

@ -9,6 +9,7 @@ from django.views import View
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from bookwyrm import models from bookwyrm import models
from bookwyrm.views.shelf.shelf_actions import unshelve
from .status import CreateStatus from .status import CreateStatus
from .helpers import get_edition, handle_reading_status, is_api_request from .helpers import get_edition, handle_reading_status, is_api_request
from .helpers import load_date_in_user_tz_as_utc from .helpers import load_date_in_user_tz_as_utc
@ -16,6 +17,7 @@ from .helpers import load_date_in_user_tz_as_utc
@method_decorator(login_required, name="dispatch") @method_decorator(login_required, name="dispatch")
# pylint: disable=no-self-use # pylint: disable=no-self-use
# pylint: disable=too-many-return-statements
class ReadingStatus(View): class ReadingStatus(View):
"""consider reading a book""" """consider reading a book"""
@ -89,8 +91,21 @@ class ReadingStatus(View):
privacy = request.POST.get("privacy") privacy = request.POST.get("privacy")
handle_reading_status(request.user, desired_shelf, book, privacy) handle_reading_status(request.user, desired_shelf, book, privacy)
# if the request includes a "shelf" value we are using the 'move' button
if bool(request.POST.get("shelf")):
# unshelve the existing shelf
this_shelf = request.POST.get("shelf")
if (
bool(current_status_shelfbook)
and int(this_shelf) != int(current_status_shelfbook.shelf.id)
and current_status_shelfbook.shelf.identifier
!= desired_shelf.identifier
):
return unshelve(request, book_id=book_id)
if is_api_request(request): if is_api_request(request):
return HttpResponse() return HttpResponse()
return redirect(referer) return redirect(referer)

View file

@ -91,13 +91,13 @@ def shelve(request):
@login_required @login_required
@require_POST @require_POST
def unshelve(request): def unshelve(request, book_id=False):
"""remove a book from a user's shelf""" """remove a book from a user's shelf"""
book = get_object_or_404(models.Edition, id=request.POST.get("book")) identity = book_id if book_id else request.POST.get("book")
book = get_object_or_404(models.Edition, id=identity)
shelf_book = get_object_or_404( shelf_book = get_object_or_404(
models.ShelfBook, book=book, shelf__id=request.POST["shelf"] models.ShelfBook, book=book, shelf__id=request.POST["shelf"]
) )
shelf_book.raise_not_deletable(request.user) shelf_book.raise_not_deletable(request.user)
shelf_book.delete() shelf_book.delete()
return redirect(request.headers.get("Referer", "/")) return redirect(request.headers.get("Referer", "/"))

View file

@ -54,6 +54,7 @@ class CreateStatus(View):
data = {"book": book} data = {"book": book}
return TemplateResponse(request, "compose.html", data) return TemplateResponse(request, "compose.html", data)
# pylint: disable=too-many-branches
def post(self, request, status_type, existing_status_id=None): def post(self, request, status_type, existing_status_id=None):
"""create status of whatever type""" """create status of whatever type"""
created = not existing_status_id created = not existing_status_id
@ -117,11 +118,12 @@ class CreateStatus(View):
status.save(created=created) status.save(created=created)
# update a readthorugh, if needed # update a readthrough, if needed
try: if bool(request.POST.get("id")):
edit_readthrough(request) try:
except Http404: edit_readthrough(request)
pass except Http404:
pass
if is_api_request(request): if is_api_request(request):
return HttpResponse() return HttpResponse()