From fdf5113143fa3ac9fac806f5547e0a03b8c63e3b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 8 Apr 2021 16:00:57 -0700 Subject: [PATCH 01/49] Removes tag code --- bookwyrm/models/__init__.py | 2 - bookwyrm/models/tag.py | 63 ---------------- bookwyrm/tests/views/test_tag.py | 119 ------------------------------- bookwyrm/urls.py | 5 -- bookwyrm/views/__init__.py | 1 - bookwyrm/views/tag.py | 73 ------------------- 6 files changed, 263 deletions(-) delete mode 100644 bookwyrm/models/tag.py delete mode 100644 bookwyrm/tests/views/test_tag.py delete mode 100644 bookwyrm/views/tag.py diff --git a/bookwyrm/models/__init__.py b/bookwyrm/models/__init__.py index 35e32c2c..2a25a525 100644 --- a/bookwyrm/models/__init__.py +++ b/bookwyrm/models/__init__.py @@ -17,8 +17,6 @@ from .favorite import Favorite from .notification import Notification from .readthrough import ReadThrough, ProgressUpdate, ProgressMode -from .tag import Tag, UserTag - from .user import User, KeyPair, AnnualGoal from .relationship import UserFollows, UserFollowRequest, UserBlocks from .report import Report, ReportComment diff --git a/bookwyrm/models/tag.py b/bookwyrm/models/tag.py deleted file mode 100644 index 2c45b8f9..00000000 --- a/bookwyrm/models/tag.py +++ /dev/null @@ -1,63 +0,0 @@ -""" models for storing different kinds of Activities """ -import urllib.parse - -from django.apps import apps -from django.db import models - -from bookwyrm import activitypub -from bookwyrm.settings import DOMAIN -from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin -from .base_model import BookWyrmModel -from . import fields - - -class Tag(OrderedCollectionMixin, BookWyrmModel): - """ freeform tags for books """ - - name = fields.CharField(max_length=100, unique=True) - identifier = models.CharField(max_length=100) - - @property - def books(self): - """ count of books associated with this tag """ - edition_model = apps.get_model("bookwyrm.Edition", require_ready=True) - return ( - edition_model.objects.filter(usertag__tag__identifier=self.identifier) - .order_by("-created_date") - .distinct() - ) - - collection_queryset = books - - def get_remote_id(self): - """ tag should use identifier not id in remote_id """ - base_path = "https://%s" % DOMAIN - return "%s/tag/%s" % (base_path, self.identifier) - - def save(self, *args, **kwargs): - """ create a url-safe lookup key for the tag """ - if not self.id: - # add identifiers to new tags - self.identifier = urllib.parse.quote_plus(self.name) - super().save(*args, **kwargs) - - -class UserTag(CollectionItemMixin, BookWyrmModel): - """ an instance of a tag on a book by a user """ - - user = fields.ForeignKey( - "User", on_delete=models.PROTECT, activitypub_field="actor" - ) - book = fields.ForeignKey( - "Edition", on_delete=models.PROTECT, activitypub_field="object" - ) - tag = fields.ForeignKey("Tag", on_delete=models.PROTECT, activitypub_field="target") - - activity_serializer = activitypub.Add - object_field = "book" - collection_field = "tag" - - class Meta: - """ unqiueness constraint """ - - unique_together = ("user", "book", "tag") diff --git a/bookwyrm/tests/views/test_tag.py b/bookwyrm/tests/views/test_tag.py deleted file mode 100644 index 6ad6ab25..00000000 --- a/bookwyrm/tests/views/test_tag.py +++ /dev/null @@ -1,119 +0,0 @@ -""" test for app action functionality """ -from unittest.mock import patch -from django.contrib.auth.models import Group, Permission -from django.contrib.contenttypes.models import ContentType -from django.template.response import TemplateResponse -from django.test import TestCase -from django.test.client import RequestFactory - -from bookwyrm import models, views -from bookwyrm.activitypub import ActivitypubResponse - - -class TagViews(TestCase): - """ tag views""" - - def setUp(self): - """ we need basic test data and mocks """ - self.factory = RequestFactory() - self.local_user = models.User.objects.create_user( - "mouse@local.com", - "mouse@mouse.com", - "mouseword", - local=True, - localname="mouse", - remote_id="https://example.com/users/mouse", - ) - self.group = Group.objects.create(name="editor") - self.group.permissions.add( - Permission.objects.create( - name="edit_book", - codename="edit_book", - content_type=ContentType.objects.get_for_model(models.User), - ).id - ) - self.work = models.Work.objects.create(title="Test Work") - self.book = models.Edition.objects.create( - title="Example Edition", - remote_id="https://example.com/book/1", - parent_work=self.work, - ) - models.SiteSettings.objects.create() - - def test_tag_page(self): - """ there are so many views, this just makes sure it LOADS """ - view = views.Tag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="hi there") - models.UserTag.objects.create(tag=tag, user=self.local_user, book=self.book) - request = self.factory.get("") - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = False - result = view(request, tag.identifier) - self.assertIsInstance(result, TemplateResponse) - result.render() - self.assertEqual(result.status_code, 200) - - request = self.factory.get("") - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = True - result = view(request, tag.identifier) - self.assertIsInstance(result, ActivitypubResponse) - self.assertEqual(result.status_code, 200) - - def test_tag_page_activitypub_page(self): - """ there are so many views, this just makes sure it LOADS """ - view = views.Tag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="hi there") - models.UserTag.objects.create(tag=tag, user=self.local_user, book=self.book) - request = self.factory.get("", {"page": 1}) - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = True - result = view(request, tag.identifier) - self.assertIsInstance(result, ActivitypubResponse) - self.assertEqual(result.status_code, 200) - - def test_tag(self): - """ add a tag to a book """ - view = views.AddTag.as_view() - request = self.factory.post( - "", - { - "name": "A Tag!?", - "book": self.book.id, - }, - ) - request.user = self.local_user - - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - view(request) - - tag = models.Tag.objects.get() - user_tag = models.UserTag.objects.get() - self.assertEqual(tag.name, "A Tag!?") - self.assertEqual(tag.identifier, "A+Tag%21%3F") - self.assertEqual(user_tag.user, self.local_user) - self.assertEqual(user_tag.book, self.book) - - def test_untag(self): - """ remove a tag from a book """ - view = views.RemoveTag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="A Tag!?") - models.UserTag.objects.create(user=self.local_user, book=self.book, tag=tag) - request = self.factory.post( - "", - { - "user": self.local_user.id, - "book": self.book.id, - "name": tag.name, - }, - ) - request.user = self.local_user - - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - view(request) - - self.assertTrue(models.Tag.objects.filter(name="A Tag!?").exists()) - self.assertFalse(models.UserTag.objects.exists()) diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 46398806..0e48ef90 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -245,11 +245,6 @@ urlpatterns = [ # author re_path(r"^author/(?P\d+)(.json)?/?$", views.Author.as_view()), re_path(r"^author/(?P\d+)/edit/?$", views.EditAuthor.as_view()), - # tags - re_path(r"^tag/(?P.+)\.json/?$", views.Tag.as_view()), - re_path(r"^tag/(?P.+)/?$", views.Tag.as_view()), - re_path(r"^tag/?$", views.AddTag.as_view()), - re_path(r"^untag/?$", views.RemoveTag.as_view()), # reading progress re_path(r"^edit-readthrough/?$", views.edit_readthrough, name="edit-readthrough"), re_path(r"^delete-readthrough/?$", views.delete_readthrough), diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index d053e971..d73a79ed 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -32,7 +32,6 @@ from .shelf import create_shelf, delete_shelf from .shelf import shelve, unshelve from .site import Site from .status import CreateStatus, DeleteStatus, DeleteAndRedraft -from .tag import Tag, AddTag, RemoveTag from .updates import get_notification_count, get_unread_status_count from .user import User, EditUser, Followers, Following from .user_admin import UserAdmin diff --git a/bookwyrm/views/tag.py b/bookwyrm/views/tag.py deleted file mode 100644 index a6bdf05a..00000000 --- a/bookwyrm/views/tag.py +++ /dev/null @@ -1,73 +0,0 @@ -""" tagging views""" -from django.contrib.auth.decorators import login_required -from django.shortcuts import get_object_or_404, redirect -from django.template.response import TemplateResponse -from django.utils.decorators import method_decorator -from django.views import View - -from bookwyrm import models -from bookwyrm.activitypub import ActivitypubResponse -from .helpers import is_api_request - - -# pylint: disable= no-self-use -class Tag(View): - """ tag page """ - - def get(self, request, tag_id): - """ see books related to a tag """ - tag_obj = get_object_or_404(models.Tag, identifier=tag_id) - - if is_api_request(request): - return ActivitypubResponse(tag_obj.to_activity(**request.GET)) - - books = models.Edition.objects.filter( - usertag__tag__identifier=tag_id - ).distinct() - data = { - "books": books, - "tag": tag_obj, - } - return TemplateResponse(request, "tag.html", data) - - -@method_decorator(login_required, name="dispatch") -class AddTag(View): - """ add a tag to a book """ - - def post(self, request): - """ tag a book """ - # I'm not using a form here because sometimes "name" is sent as a hidden - # field which doesn't validate - name = request.POST.get("name") - book_id = request.POST.get("book") - book = get_object_or_404(models.Edition, id=book_id) - tag_obj, _ = models.Tag.objects.get_or_create( - name=name, - ) - models.UserTag.objects.get_or_create( - user=request.user, - book=book, - tag=tag_obj, - ) - - return redirect("/book/%s" % book_id) - - -@method_decorator(login_required, name="dispatch") -class RemoveTag(View): - """ remove a user's tag from a book """ - - def post(self, request): - """ untag a book """ - name = request.POST.get("name") - tag_obj = get_object_or_404(models.Tag, name=name) - book_id = request.POST.get("book") - book = get_object_or_404(models.Edition, id=book_id) - - user_tag = get_object_or_404( - models.UserTag, tag=tag_obj, book=book, user=request.user - ) - user_tag.delete() - - return redirect("/book/%s" % book_id) From 58aeb72afa6f28ead18888d47438e0704a424e23 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 17:23:48 +0200 Subject: [PATCH 02/49] Move card footer container inside the card-footer component --- bookwyrm/templates/components/card.html | 6 +-- .../templates/moderation/report_preview.html | 38 ++++++++++--------- bookwyrm/templates/snippets/goal_card.html | 12 +++--- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/bookwyrm/templates/components/card.html b/bookwyrm/templates/components/card.html index f1104893..7dc3e1b0 100644 --- a/bookwyrm/templates/components/card.html +++ b/bookwyrm/templates/components/card.html @@ -11,10 +11,8 @@ {% endif %} -
- {% block card-footer %} - {% endblock %} -
+ {% block card-footer %} + {% endblock %} {% block card-bonus %} {% endblock %} diff --git a/bookwyrm/templates/moderation/report_preview.html b/bookwyrm/templates/moderation/report_preview.html index 363783d5..936c04b8 100644 --- a/bookwyrm/templates/moderation/report_preview.html +++ b/bookwyrm/templates/moderation/report_preview.html @@ -16,22 +16,24 @@ {% endblock %} {% block card-footer %} - - - +
+ + + +
{% endblock %} diff --git a/bookwyrm/templates/snippets/goal_card.html b/bookwyrm/templates/snippets/goal_card.html index 329fea54..5014b81c 100644 --- a/bookwyrm/templates/snippets/goal_card.html +++ b/bookwyrm/templates/snippets/goal_card.html @@ -17,9 +17,11 @@ {% endblock %} {% block card-footer %} - +
+ +
{% endblock %} From 13957c2f4424187c9af786d6fa98dfe6560d6143 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 21 Apr 2021 17:32:35 +0200 Subject: [PATCH 03/49] Move footer some items to header - Header elements are now enclosed in a media layout - Footer elements are not in a card-footer anymore --- .../templates/snippets/status/layout.html | 15 +- .../snippets/status/status_header.html | 142 ++++++++++-------- 2 files changed, 81 insertions(+), 76 deletions(-) diff --git a/bookwyrm/templates/snippets/status/layout.html b/bookwyrm/templates/snippets/status/layout.html index 5b6c0c78..9c9d8fc1 100644 --- a/bookwyrm/templates/snippets/status/layout.html +++ b/bookwyrm/templates/snippets/status/layout.html @@ -13,7 +13,7 @@ {% block card-content %}{% endblock %} {% block card-footer %} -