Merge branch 'main' into remote-follow
This commit is contained in:
@ -296,7 +296,7 @@ class ManyToManyField(ActivitypubFieldMixin, models.ManyToManyField):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def set_field_from_activity(self, instance, data, overwrite=True):
|
||||
"""helper function for assinging a value to the field"""
|
||||
"""helper function for assigning a value to the field"""
|
||||
if not overwrite and getattr(instance, self.name).exists():
|
||||
return False
|
||||
|
||||
@ -398,7 +398,11 @@ class ImageField(ActivitypubFieldMixin, models.ImageField):
|
||||
if formatted is None or formatted is MISSING:
|
||||
return False
|
||||
|
||||
if not overwrite and hasattr(instance, self.name):
|
||||
if (
|
||||
not overwrite
|
||||
and hasattr(instance, self.name)
|
||||
and getattr(instance, self.name)
|
||||
):
|
||||
return False
|
||||
|
||||
getattr(instance, self.name).save(*formatted, save=save)
|
||||
|
@ -45,6 +45,13 @@ let BookWyrm = new class {
|
||||
'change',
|
||||
this.disableIfTooLarge.bind(this)
|
||||
));
|
||||
|
||||
document.querySelectorAll('[data-duplicate]')
|
||||
.forEach(node => node.addEventListener(
|
||||
'click',
|
||||
this.duplicateInput.bind(this)
|
||||
|
||||
))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -383,4 +390,24 @@ let BookWyrm = new class {
|
||||
"left=100,top=100,width=430,height=600"
|
||||
);
|
||||
}
|
||||
|
||||
duplicateInput (event ) {
|
||||
const trigger = event.currentTarget;
|
||||
const input_id = trigger.dataset['duplicate']
|
||||
const orig = document.getElementById(input_id);
|
||||
const parent = orig.parentNode;
|
||||
const new_count = parent.querySelectorAll("input").length + 1
|
||||
|
||||
let input = orig.cloneNode();
|
||||
|
||||
input.id += ("-" + (new_count))
|
||||
input.value = ""
|
||||
|
||||
let label = parent.querySelector("label").cloneNode();
|
||||
|
||||
label.setAttribute("for", input.id)
|
||||
|
||||
parent.appendChild(label)
|
||||
parent.appendChild(input)
|
||||
}
|
||||
}();
|
||||
|
@ -187,6 +187,7 @@ let StatusCache = new class {
|
||||
.forEach(item => BookWyrm.addRemoveClass(item, "is-hidden", false));
|
||||
|
||||
// Remove existing disabled states
|
||||
|
||||
button.querySelectorAll("[data-shelf-dropdown-identifier] button")
|
||||
.forEach(item => item.disabled = false);
|
||||
|
||||
|
@ -153,12 +153,21 @@
|
||||
|
||||
{# 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 %}
|
||||
<p>
|
||||
{% 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 %}
|
||||
{% include 'snippets/shelf_selector.html' with current=shelf.shelf %}
|
||||
</p>
|
||||
<li class="box">
|
||||
{% blocktrans with path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}<a href="{{ path }}">{{ shelf_name }}</a>{% endblocktrans %}
|
||||
<div class="mb-3">
|
||||
{% 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.name %}A <a href="{{ book_path }}">different edition</a> of this book is on your <a href="{{ shelf_path }}">{{ shelf_name }}</a> shelf.{% endblocktrans %}
|
||||
|
@ -119,10 +119,16 @@
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_add_author">{% trans "Add Authors:" %}</label>
|
||||
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="{% trans 'John Doe, Jane Smith' %}" value="{{ add_author }}" {% if confirm_mode %}readonly{% endif %}>
|
||||
<span class="help">{% trans "Separate multiple values with commas." %}</span>
|
||||
<label class="label">{% trans "Add Authors:" %}</label>
|
||||
{% for author in add_author %}
|
||||
<label class="label is-sr-only" for="id_add_author{% if not forloop.first %}-{{forloop.counter}}{% endif %}">{% trans "Add Author" %}</label>
|
||||
<input class="input" type="text" name="add_author" id="id_add_author{% if not forloop.first %}-{{forloop.counter}}{% endif %}" placeholder="{% trans 'Jane Doe' %}" value="{{ author }}" {% if confirm_mode %}readonly{% endif %}>
|
||||
{% empty %}
|
||||
<label class="label is-sr-only" for="id_add_author">{% trans "Add Author" %}</label>
|
||||
<input class="input" type="text" name="add_author" id="id_add_author" placeholder="{% trans 'Jane Doe' %}" value="{{ author }}" {% if confirm_mode %}readonly{% endif %}>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<span class="help"><button class="button is-small" type="button" data-duplicate="id_add_author" id="another_author_field">{% trans "Add Another Author" %}</button></span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -9,10 +9,11 @@ Finish "<em>{{ book_title }}</em>"
|
||||
{% endblock %}
|
||||
|
||||
{% 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 %}
|
||||
<input type="hidden" name="id" value="{{ readthrough.id }}">
|
||||
<input type="hidden" name="reading_status" value="read">
|
||||
<input type="hidden" name="shelf" value="{{ move_from }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block reading-dates %}
|
||||
|
@ -9,8 +9,9 @@ Start "<em>{{ book_title }}</em>"
|
||||
{% endblock %}
|
||||
|
||||
{% 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="shelf" value="{{ move_from }}">
|
||||
{% csrf_token %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -9,8 +9,9 @@ Want to Read "<em>{{ book_title }}</em>"
|
||||
{% endblock %}
|
||||
|
||||
{% 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="shelf" value="{{ move_from }}">
|
||||
{% csrf_token %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -1,29 +1,88 @@
|
||||
{% extends 'components/dropdown.html' %}
|
||||
{% load i18n %}
|
||||
{% load bookwyrm_tags %}
|
||||
{% load utilities %}
|
||||
|
||||
{% block dropdown-trigger %}
|
||||
<span>{% trans "Move book" %}</span>
|
||||
<span class="icon icon-arrow-down" aria-hidden="true"></span>
|
||||
{% endblock %}
|
||||
|
||||
{% 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 %}
|
||||
|
||||
{% if shelf.editable %}
|
||||
<li role="menuitem" class="dropdown-item p-0">
|
||||
<form name="shelve" action="/shelve/" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="book" value="{{ book.id }}">
|
||||
<input type="hidden" name="change-shelf-from" value="{{ current.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>
|
||||
</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 %}
|
||||
<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">
|
||||
<form name="shelve" action="/unshelve/" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="book" value="{{ book.id }}">
|
||||
<input type="hidden" name="shelf" value="{{ current.id }}">
|
||||
<button class="button is-fullwidth is-small is-radiusless is-danger is-light" type="submit">{% trans "Remove" %}</button>
|
||||
<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 from" %} {{ shelved_in.name }}</button>
|
||||
</form>
|
||||
</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 %}
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
{% elif shelf.editable %}
|
||||
|
||||
<form name="shelve" action="/shelve/" method="post">
|
||||
<form name="shelve" action="/shelve/" method="post" autocomplete="off">
|
||||
{% csrf_token %}
|
||||
<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 %}>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{% load utilities %}
|
||||
{% 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 %}
|
||||
<button
|
||||
{% if not fallback_url %}
|
||||
|
@ -77,7 +77,12 @@ def related_status(notification):
|
||||
def active_shelf(context, book):
|
||||
"""check what shelf a user has a book on, if any"""
|
||||
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 = (
|
||||
models.ShelfBook.objects.filter(
|
||||
|
@ -19,7 +19,7 @@ from django.utils import timezone
|
||||
|
||||
from bookwyrm import activitypub
|
||||
from bookwyrm.activitypub.base_activity import ActivityObject
|
||||
from bookwyrm.models import fields, User, Status
|
||||
from bookwyrm.models import fields, User, Status, Edition
|
||||
from bookwyrm.models.base_model import BookWyrmModel
|
||||
from bookwyrm.models.activitypub_mixin import ActivitypubMixin
|
||||
from bookwyrm.settings import DOMAIN
|
||||
@ -215,7 +215,7 @@ class ModelFields(TestCase):
|
||||
"rat", "rat@rat.rat", "ratword", local=True, localname="rat"
|
||||
)
|
||||
public = "https://www.w3.org/ns/activitystreams#Public"
|
||||
followers = "%s/followers" % user.remote_id
|
||||
followers = f"{user.remote_id}/followers"
|
||||
|
||||
instance = fields.PrivacyField()
|
||||
instance.name = "privacy_field"
|
||||
@ -409,11 +409,10 @@ class ModelFields(TestCase):
|
||||
"""loadin' a list of items from Links"""
|
||||
# TODO
|
||||
|
||||
@responses.activate
|
||||
@patch("bookwyrm.models.activitypub_mixin.ObjectMixin.broadcast")
|
||||
@patch("bookwyrm.suggested_users.remove_user_task.delay")
|
||||
def test_image_field(self, *_):
|
||||
"""storing images"""
|
||||
def test_image_field_to_activity(self, *_):
|
||||
"""serialize an image field to activitypub"""
|
||||
user = User.objects.create_user(
|
||||
"mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse"
|
||||
)
|
||||
@ -437,16 +436,155 @@ class ModelFields(TestCase):
|
||||
self.assertEqual(output.name, "")
|
||||
self.assertEqual(output.type, "Document")
|
||||
|
||||
@responses.activate
|
||||
def test_image_field_from_activity(self, *_):
|
||||
"""load an image from activitypub"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/default_avi.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
output = BytesIO()
|
||||
image.save(output, format=image.format)
|
||||
|
||||
instance = fields.ImageField()
|
||||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://www.example.com/image.jpg",
|
||||
body=user.avatar.file.read(),
|
||||
body=image.tobytes(),
|
||||
status=200,
|
||||
)
|
||||
loaded_image = instance.field_from_activity("http://www.example.com/image.jpg")
|
||||
self.assertIsInstance(loaded_image, list)
|
||||
self.assertIsInstance(loaded_image[1], ContentFile)
|
||||
|
||||
@responses.activate
|
||||
def test_image_field_set_field_from_activity(self, *_):
|
||||
"""update a model instance from an activitypub object"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/default_avi.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
output = BytesIO()
|
||||
image.save(output, format=image.format)
|
||||
|
||||
instance = fields.ImageField(activitypub_field="cover", name="cover")
|
||||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://www.example.com/image.jpg",
|
||||
body=image.tobytes(),
|
||||
status=200,
|
||||
)
|
||||
book = Edition.objects.create(title="hello")
|
||||
|
||||
MockActivity = namedtuple("MockActivity", ("cover"))
|
||||
mock_activity = MockActivity("http://www.example.com/image.jpg")
|
||||
|
||||
instance.set_field_from_activity(book, mock_activity)
|
||||
self.assertIsNotNone(book.cover.name)
|
||||
self.assertEqual(book.cover.size, 43200)
|
||||
|
||||
@responses.activate
|
||||
def test_image_field_set_field_from_activity_no_overwrite_no_cover(self, *_):
|
||||
"""update a model instance from an activitypub object"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/default_avi.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
output = BytesIO()
|
||||
image.save(output, format=image.format)
|
||||
|
||||
instance = fields.ImageField(activitypub_field="cover", name="cover")
|
||||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://www.example.com/image.jpg",
|
||||
body=image.tobytes(),
|
||||
status=200,
|
||||
)
|
||||
book = Edition.objects.create(title="hello")
|
||||
|
||||
MockActivity = namedtuple("MockActivity", ("cover"))
|
||||
mock_activity = MockActivity("http://www.example.com/image.jpg")
|
||||
|
||||
instance.set_field_from_activity(book, mock_activity, overwrite=False)
|
||||
self.assertIsNotNone(book.cover.name)
|
||||
self.assertEqual(book.cover.size, 43200)
|
||||
|
||||
@responses.activate
|
||||
def test_image_field_set_field_from_activity_no_overwrite_with_cover(self, *_):
|
||||
"""update a model instance from an activitypub object"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/default_avi.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
output = BytesIO()
|
||||
image.save(output, format=image.format)
|
||||
|
||||
another_image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/logo.png"
|
||||
)
|
||||
another_image = Image.open(another_image_file)
|
||||
another_output = BytesIO()
|
||||
another_image.save(another_output, format=another_image.format)
|
||||
|
||||
instance = fields.ImageField(activitypub_field="cover", name="cover")
|
||||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://www.example.com/image.jpg",
|
||||
body=another_image.tobytes(),
|
||||
status=200,
|
||||
)
|
||||
book = Edition.objects.create(title="hello")
|
||||
book.cover.save("test.jpg", ContentFile(output.getvalue()))
|
||||
self.assertEqual(book.cover.size, 2136)
|
||||
|
||||
MockActivity = namedtuple("MockActivity", ("cover"))
|
||||
mock_activity = MockActivity("http://www.example.com/image.jpg")
|
||||
|
||||
instance.set_field_from_activity(book, mock_activity, overwrite=False)
|
||||
# same cover as before
|
||||
self.assertEqual(book.cover.size, 2136)
|
||||
|
||||
@responses.activate
|
||||
def test_image_field_set_field_from_activity_with_overwrite_with_cover(self, *_):
|
||||
"""update a model instance from an activitypub object"""
|
||||
image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/default_avi.jpg"
|
||||
)
|
||||
image = Image.open(image_file)
|
||||
output = BytesIO()
|
||||
image.save(output, format=image.format)
|
||||
book = Edition.objects.create(title="hello")
|
||||
book.cover.save("test.jpg", ContentFile(output.getvalue()))
|
||||
self.assertEqual(book.cover.size, 2136)
|
||||
|
||||
another_image_file = pathlib.Path(__file__).parent.joinpath(
|
||||
"../../static/images/logo.png"
|
||||
)
|
||||
another_image = Image.open(another_image_file)
|
||||
another_output = BytesIO()
|
||||
another_image.save(another_output, format=another_image.format)
|
||||
|
||||
instance = fields.ImageField(activitypub_field="cover", name="cover")
|
||||
|
||||
responses.add(
|
||||
responses.GET,
|
||||
"http://www.example.com/image.jpg",
|
||||
body=another_image.tobytes(),
|
||||
status=200,
|
||||
)
|
||||
|
||||
MockActivity = namedtuple("MockActivity", ("cover"))
|
||||
mock_activity = MockActivity("http://www.example.com/image.jpg")
|
||||
|
||||
instance.set_field_from_activity(book, mock_activity, overwrite=True)
|
||||
# new cover
|
||||
self.assertIsNotNone(book.cover.name)
|
||||
self.assertEqual(book.cover.size, 376800)
|
||||
|
||||
def test_datetime_field(self, *_):
|
||||
"""this one is pretty simple, it just has to use isoformat"""
|
||||
instance = fields.DateTimeField()
|
||||
|
@ -51,13 +51,14 @@ class EditBook(View):
|
||||
if not form.is_valid():
|
||||
return TemplateResponse(request, "book/edit/edit_book.html", data)
|
||||
|
||||
add_author = request.POST.get("add_author")
|
||||
# we're adding an author through a free text field
|
||||
# filter out empty author fields
|
||||
add_author = [author for author in request.POST.getlist("add_author") if author]
|
||||
if add_author:
|
||||
data["add_author"] = add_author
|
||||
data["author_matches"] = []
|
||||
data["isni_matches"] = []
|
||||
for author in add_author.split(","):
|
||||
|
||||
for author in add_author:
|
||||
if not author:
|
||||
continue
|
||||
# check for existing authors
|
||||
|
@ -9,6 +9,7 @@ from django.views import View
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.views.shelf.shelf_actions import unshelve
|
||||
from .status import CreateStatus
|
||||
from .helpers import get_edition, handle_reading_status, is_api_request
|
||||
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")
|
||||
# pylint: disable=no-self-use
|
||||
# pylint: disable=too-many-return-statements
|
||||
class ReadingStatus(View):
|
||||
"""consider reading a book"""
|
||||
|
||||
@ -89,8 +91,21 @@ class ReadingStatus(View):
|
||||
privacy = request.POST.get("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):
|
||||
return HttpResponse()
|
||||
|
||||
return redirect(referer)
|
||||
|
||||
|
||||
|
@ -91,13 +91,13 @@ def shelve(request):
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def unshelve(request):
|
||||
def unshelve(request, book_id=False):
|
||||
"""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(
|
||||
models.ShelfBook, book=book, shelf__id=request.POST["shelf"]
|
||||
)
|
||||
shelf_book.raise_not_deletable(request.user)
|
||||
|
||||
shelf_book.delete()
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
|
@ -54,6 +54,7 @@ class CreateStatus(View):
|
||||
data = {"book": book}
|
||||
return TemplateResponse(request, "compose.html", data)
|
||||
|
||||
# pylint: disable=too-many-branches
|
||||
def post(self, request, status_type, existing_status_id=None):
|
||||
"""create status of whatever type"""
|
||||
created = not existing_status_id
|
||||
@ -117,11 +118,12 @@ class CreateStatus(View):
|
||||
|
||||
status.save(created=created)
|
||||
|
||||
# update a readthorugh, if needed
|
||||
try:
|
||||
edit_readthrough(request)
|
||||
except Http404:
|
||||
pass
|
||||
# update a readthrough, if needed
|
||||
if bool(request.POST.get("id")):
|
||||
try:
|
||||
edit_readthrough(request)
|
||||
except Http404:
|
||||
pass
|
||||
|
||||
if is_api_request(request):
|
||||
return HttpResponse()
|
||||
|
Reference in New Issue
Block a user