mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-12-13 03:36:35 +00:00
Merge branch 'main' into production
This commit is contained in:
commit
a0b0edbc3e
13 changed files with 157 additions and 76 deletions
34
bookwyrm/management/commands/remove_editions.py
Normal file
34
bookwyrm/management/commands/remove_editions.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
''' PROCEED WITH CAUTION: this permanently deletes book data '''
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count, Q
|
||||
from bookwyrm import models
|
||||
|
||||
|
||||
def remove_editions():
|
||||
''' combine duplicate editions and update related models '''
|
||||
# not in use
|
||||
filters = {'%s__isnull' % r.name: True \
|
||||
for r in models.Edition._meta.related_objects}
|
||||
# no cover, no identifying fields
|
||||
filters['cover'] = ''
|
||||
null_fields = {'%s__isnull' % f: True for f in \
|
||||
['isbn_10', 'isbn_13', 'oclc_number']}
|
||||
|
||||
editions = models.Edition.objects.filter(
|
||||
Q(languages=[]) | Q(languages__contains=['English']),
|
||||
**filters, **null_fields
|
||||
).annotate(Count('parent_work__editions')).filter(
|
||||
# mustn't be the only edition for the work
|
||||
parent_work__editions__count__gt=1
|
||||
)
|
||||
print(editions.count())
|
||||
editions.delete()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
''' dedplucate allllll the book data models '''
|
||||
help = 'merges duplicate book data'
|
||||
# pylint: disable=no-self-use,unused-argument
|
||||
def handle(self, *args, **options):
|
||||
''' run deudplications '''
|
||||
remove_editions()
|
13
bookwyrm/templates/components/inline_form.html
Normal file
13
bookwyrm/templates/components/inline_form.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<section class="card hidden {{ class }}" id="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}">
|
||||
<header class="card-header has-background-white-ter">
|
||||
<h2 class="card-header-title" tabindex="0" id="{{ controls_text }}{% if controls_uid %}-{{ controls_uid }}{% endif %}-header">
|
||||
{% block header %}{% endblock %}
|
||||
</h2>
|
||||
<span class="card-header-icon">
|
||||
{% include 'snippets/toggle/toggle_button.html' with label="Close" class="delete" nonbutton=True controls_text=controls_text %}
|
||||
</span>
|
||||
</header>
|
||||
<section class="card-content content">
|
||||
{% block form %}{% endblock %}
|
||||
</section>
|
||||
</section>
|
11
bookwyrm/templates/lists/create_form.html
Normal file
11
bookwyrm/templates/lists/create_form.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% extends 'components/inline_form.html' %}
|
||||
|
||||
{% block header %}
|
||||
Create List
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
<form name="create-list" method="post" action="{% url 'lists' %}">
|
||||
{% include 'lists/form.html' %}
|
||||
</form>
|
||||
{% endblock %}
|
11
bookwyrm/templates/lists/edit_form.html
Normal file
11
bookwyrm/templates/lists/edit_form.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% extends 'components/inline_form.html' %}
|
||||
|
||||
{% block header %}
|
||||
Edit List
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
<form name="edit-list" method="post" action="{% url 'list' list.id %}">
|
||||
{% include 'lists/form.html' %}
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -9,8 +9,8 @@
|
|||
</h4>
|
||||
</header>
|
||||
<div class="card-image is-flex">
|
||||
{% for book in list.books.all|slice:5 %}
|
||||
{% include 'snippets/book_cover.html' with book=book size="small" %}
|
||||
{% for book in list.listitem_set.all|slice:5 %}
|
||||
{% include 'snippets/book_cover.html' with book=book.book size="small" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="card-content is-flex-grow-0">
|
||||
|
|
|
@ -15,15 +15,9 @@
|
|||
{% endif %}
|
||||
</header>
|
||||
|
||||
<form name="edit-list" method="post" action="{% url 'list' list.id %}" class="box hidden" id="edit-list">
|
||||
<header class="columns">
|
||||
<h3 class="title column" tabindex="0" id="edit-list-header">Edit list</h3>
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/toggle/toggle_button.html' with controls_text="edit-list" label="close" class="delete" nonbutton=True %}
|
||||
</div>
|
||||
</header>
|
||||
{% include 'lists/form.html' %}
|
||||
</form>
|
||||
<div class="block">
|
||||
{% include 'lists/edit_form.html' with controls_text="edit-list" %}
|
||||
</div>
|
||||
|
||||
{% block panel %}{% endblock %}
|
||||
|
||||
|
|
|
@ -5,26 +5,20 @@
|
|||
<h1 class="title">Lists</h1>
|
||||
</header>
|
||||
{% if request.user.is_authenticated and not lists.has_previous %}
|
||||
<section class="block content">
|
||||
<header class="columns">
|
||||
<div class="column">
|
||||
<h2 class="title">Your lists</h2>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/toggle/open_button.html' with controls_text="create-list" icon="plus" text="Create new list" focus="create-list-header" %}
|
||||
</div>
|
||||
</header>
|
||||
<header class="block columns">
|
||||
<div class="column">
|
||||
<h2 class="title">Your lists</h2>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/toggle/open_button.html' with controls_text="create-list" icon="plus" text="Create new list" focus="create-list-header" %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form name="create-list" method="post" action="{% url 'lists' %}" class="box hidden" id="create-list">
|
||||
<header class="columns">
|
||||
<h3 class="title column" tabindex="0" id="create-list-header">Create list</h3>
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/toggle/toggle_button.html' with controls_text="create-list" label="Close" class="delete" nonbutton=True %}
|
||||
</div>
|
||||
</header>
|
||||
{% include 'lists/form.html' %}
|
||||
</form>
|
||||
<div class="block">
|
||||
{% include 'lists/create_form.html' with controls_text="create-list" %}
|
||||
</div>
|
||||
|
||||
<div class="block content">
|
||||
{% if request.user.list_set.exists %}
|
||||
{% include 'lists/list_items.html' with lists=request.user.list_set.all|slice:4 %}
|
||||
{% endif %}
|
||||
|
@ -39,9 +33,7 @@
|
|||
{% if lists %}
|
||||
<section class="block content">
|
||||
<h2 class="title">Recent Lists</h2>
|
||||
{% if request.user.list_set.exists %}
|
||||
{% include 'lists/list_items.html' with lists=lists %}
|
||||
{% endif %}
|
||||
</section>
|
||||
<div>
|
||||
{% include 'snippets/pagination.html' with page=lists path=path %}
|
||||
|
|
26
bookwyrm/templates/user/create_shelf_form.html
Normal file
26
bookwyrm/templates/user/create_shelf_form.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
{% extends 'components/inline_form.html' %}
|
||||
|
||||
{% block header %}
|
||||
Create New Shelf
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
<form name="create-shelf" action="{% url 'shelf-create' %}" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="user" value="{{ request.user.id }}">
|
||||
<div class="field">
|
||||
<label class="label" for="id_name_create">Name:</label>
|
||||
<input type="text" name="name" maxlength="100" class="input" required="true" id="id_name_create">
|
||||
</div>
|
||||
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
{% include 'snippets/privacy_select.html' %}
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-primary" type="submit">Create shelf</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
31
bookwyrm/templates/user/edit_shelf_form.html
Normal file
31
bookwyrm/templates/user/edit_shelf_form.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
{% extends 'components/inline_form.html' %}
|
||||
|
||||
{% block header %}
|
||||
Edit Shelf
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
<form name="edit-shelf" action="{{ shelf.local_path }}" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="user" value="{{ request.user.id }}">
|
||||
{% if shelf.editable %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_name">Name:</label>
|
||||
<input type="text" name="name" maxlength="100" class="input" required="true" value="{{ shelf.name }}" id="id_name">
|
||||
</div>
|
||||
{% else %}
|
||||
<input type="hidden" name="name" required="true" value="{{ shelf.name }}">
|
||||
{% endif %}
|
||||
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
{% include 'snippets/privacy_select.html' with current=shelf.privacy %}
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-primary" type="submit">Update shelf</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
|
|
@ -29,30 +29,13 @@
|
|||
|
||||
{% if is_self %}
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/toggle/open_button.html' with text="Create shelf" icon="plus" class="is-clickable" controls_text="create-shelf-form" %}
|
||||
{% include 'snippets/toggle/open_button.html' with text="Create shelf" icon="plus" controls_text="create-shelf-form" focus="create-shelf-form-header" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="hidden box mb-5" id="create-shelf-form">
|
||||
<h2 class="title is-4">Create new shelf</h2>
|
||||
<form name="create-shelf" action="/create-shelf/" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="user" value="{{ request.user.id }}">
|
||||
<div class="field">
|
||||
<label class="label" for="id_name_create">Name:</label>
|
||||
<input type="text" name="name" maxlength="100" class="input" required="true" id="id_name_create">
|
||||
</div>
|
||||
|
||||
<label class="label">
|
||||
<p>Shelf privacy:</p>
|
||||
{% include 'snippets/privacy_select.html' with no_label=True %}
|
||||
</label>
|
||||
<div class="field is-grouped">
|
||||
<button class="button is-primary" type="submit">Create shelf</button>
|
||||
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="create-shelf-form" %}
|
||||
</div>
|
||||
</form>
|
||||
<div class="block">
|
||||
{% include 'user/create_shelf_form.html' with controls_text='create-shelf-form' %}
|
||||
</div>
|
||||
|
||||
<div class="block columns">
|
||||
|
@ -66,34 +49,13 @@
|
|||
</div>
|
||||
{% if is_self %}
|
||||
<div class="column is-narrow">
|
||||
{% include 'snippets/toggle/open_button.html' with text="Edit shelf" icon="pencil" class="is-clickable" controls_text="edit-shelf-form" %}
|
||||
{% include 'snippets/toggle/open_button.html' with text="Edit shelf" icon="pencil" controls_text="edit-shelf-form" focus="edit-shelf-form-header" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="hidden box mb-5" id="edit-shelf-form">
|
||||
<h2 class="title is-4">Edit shelf</h2>
|
||||
<form name="create-shelf" action="{{ shelf.local_path }}" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="user" value="{{ request.user.id }}">
|
||||
{% if shelf.editable %}
|
||||
<div class="field">
|
||||
<label class="label" for="id_name">Name:</label>
|
||||
<input type="text" name="name" maxlength="100" class="input" required="true" value="{{ shelf.name }}" id="id_name">
|
||||
</div>
|
||||
{% else %}
|
||||
<input type="hidden" name="name" required="true" value="{{ shelf.name }}">
|
||||
{% endif %}
|
||||
|
||||
<label class="label">
|
||||
<p>Shelf privacy:</p>
|
||||
{% include 'snippets/privacy_select.html' with no_label=True current=shelf.privacy %}
|
||||
</label>
|
||||
<div class="field is-grouped">
|
||||
<button class="button is-primary" type="submit">Update shelf</button>
|
||||
{% include 'snippets/toggle/close_button.html' with text="Cancel" controls_text="edit-shelf-form" %}
|
||||
</div>
|
||||
</form>
|
||||
<div class="block">
|
||||
{% include 'user/edit_shelf_form.html' with controls_text="edit-shelf-form" %}
|
||||
</div>
|
||||
|
||||
<div class="block">
|
||||
|
|
|
@ -192,9 +192,15 @@ class Openlibrary(TestCase):
|
|||
self.assertEqual(edition['key'], '/books/OL9788823M')
|
||||
|
||||
|
||||
@responses.activate
|
||||
def test_create_edition_from_data(self):
|
||||
''' okay but can it actually create an edition with proper metadata '''
|
||||
work = models.Work.objects.create(title='Hello')
|
||||
responses.add(
|
||||
responses.GET,
|
||||
'https://openlibrary.org/authors/OL382982A',
|
||||
json={'hi': 'there'},
|
||||
status=200)
|
||||
result = self.connector.create_edition_from_data(
|
||||
work, self.edition_data)
|
||||
self.assertEqual(result.parent_work, work)
|
||||
|
|
|
@ -150,7 +150,7 @@ urlpatterns = [
|
|||
user_path, views.Shelf.as_view(), name='shelf'),
|
||||
re_path(r'^%s/shelf/(?P<shelf_identifier>[\w-]+)(.json)?/?$' % \
|
||||
local_user_path, views.Shelf.as_view()),
|
||||
re_path(r'^create-shelf/?$', views.create_shelf),
|
||||
re_path(r'^create-shelf/?$', views.create_shelf, name='shelf-create'),
|
||||
re_path(r'^delete-shelf/(?P<shelf_id>\d+)?$', views.delete_shelf),
|
||||
re_path(r'^shelve/?$', views.shelve),
|
||||
re_path(r'^unshelve/?$', views.unshelve),
|
||||
|
|
|
@ -29,6 +29,7 @@ class Lists(View):
|
|||
user = request.user if request.user.is_authenticated else None
|
||||
lists = models.List.objects.filter(
|
||||
~Q(user=user),
|
||||
books__isnull=False,
|
||||
).all()
|
||||
lists = privacy_filter(request.user, lists, ['public', 'followers'])
|
||||
|
||||
|
|
Loading…
Reference in a new issue