From 8ba875af4a4b936e9b2d513489918df6ef3aa28d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 26 Oct 2021 14:37:43 -0700 Subject: [PATCH 001/217] Improve federation compability with Hubzilla and Zap Co-authored-by: hubzilla Fixes #1564 --- bookwyrm/connectors/abstract_connector.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index c032986d1..79d79be4d 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -227,8 +227,12 @@ def get_data(url, params=None, timeout=10): resp = requests.get( url, params=params, - headers={ - "Accept": "application/json; charset=utf-8", + headers={ # pylint: disable=line-too-long + "Accept": ( + "application/activity+json," + ' application/ld+json; profile="https://www.w3.org/ns/activitystreams",' + " application/json; charset=utf-8" + ), "User-Agent": settings.USER_AGENT, }, timeout=timeout, From 07446fa7d207857d0997753df4c5a5b746f94fac Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 27 Oct 2021 10:03:09 -0700 Subject: [PATCH 002/217] Adds more tests for the inventaire connector --- bookwyrm/connectors/inventaire.py | 5 +- .../connectors/test_inventaire_connector.py | 119 ++++++++++++++++++ 2 files changed, 121 insertions(+), 3 deletions(-) diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index faed5429a..43aee2f43 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -104,9 +104,7 @@ class Connector(AbstractConnector): def parse_isbn_search_data(self, data): """got some daaaata""" - results = data.get("entities") - if not results: - return [] + results = data.get("entities", []) return list(results.values()) def format_isbn_search_result(self, search_result): @@ -128,6 +126,7 @@ class Connector(AbstractConnector): def load_edition_data(self, work_uri): """get a list of editions for a work""" + # pylint: disable=line-too-long url = f"{self.books_url}?action=reverse-claims&property=wdt:P629&value={work_uri}&sort=true" return get_data(url) diff --git a/bookwyrm/tests/connectors/test_inventaire_connector.py b/bookwyrm/tests/connectors/test_inventaire_connector.py index 381017727..6536bae71 100644 --- a/bookwyrm/tests/connectors/test_inventaire_connector.py +++ b/bookwyrm/tests/connectors/test_inventaire_connector.py @@ -1,11 +1,14 @@ """ testing book data connectors """ import json import pathlib +from unittest.mock import patch + from django.test import TestCase import responses from bookwyrm import models from bookwyrm.connectors.inventaire import Connector, get_language_code +from bookwyrm.connectors.connector_manager import ConnectorException class Inventaire(TestCase): @@ -48,6 +51,44 @@ class Inventaire(TestCase): self.assertEqual(result["wdt:P31"], ["wd:Q3331189"]) self.assertEqual(result["uri"], "isbn:9780375757853") + @responses.activate + def test_get_book_data_invalid(self): + """error if there isn't any entity data""" + responses.add( + responses.GET, + "https://test.url/ok", + json={ + "entities": {}, + "redirects": {}, + }, + ) + + with self.assertRaises(ConnectorException): + self.connector.get_book_data("https://test.url/ok") + + @responses.activate + def test_search(self): + """min confidence filtering""" + responses.add( + responses.GET, + "https://inventaire.io/search?q=hi", + json={ + "results": [ + { + "_score": 200, + "label": "hello", + }, + { + "_score": 100, + "label": "hi", + }, + ], + }, + ) + results = self.connector.search("hi", min_confidence=0.5) + self.assertEqual(len(results), 1) + self.assertEqual(results[0].title, "hello") + def test_format_search_result(self): """json to search result objs""" search_file = pathlib.Path(__file__).parent.joinpath( @@ -157,6 +198,84 @@ class Inventaire(TestCase): "https://covers.inventaire.io/img/entities/12345", ) + def test_isbn_search_empty(self): + """another search type""" + search_results = {} + results = self.connector.parse_isbn_search_data(search_results) + self.assertEqual(results, []) + + def test_isbn_search_no_title(self): + """another search type""" + search_file = pathlib.Path(__file__).parent.joinpath( + "../data/inventaire_isbn_search.json" + ) + search_results = json.loads(search_file.read_bytes()) + search_results["entities"]["isbn:9782290349229"]["claims"]["wdt:P1476"] = None + + result = self.connector.format_isbn_search_result( + search_results.get("entities") + ) + self.assertIsNone(result) + + def test_is_work_data(self): + """is it a work""" + work_file = pathlib.Path(__file__).parent.joinpath( + "../data/inventaire_work.json" + ) + work_data = json.loads(work_file.read_bytes()) + with patch("bookwyrm.connectors.inventaire.get_data") as get_data_mock: + get_data_mock.return_value = work_data + formatted = self.connector.get_book_data("hi") + self.assertTrue(self.connector.is_work_data(formatted)) + + edition_file = pathlib.Path(__file__).parent.joinpath( + "../data/inventaire_edition.json" + ) + edition_data = json.loads(edition_file.read_bytes()) + with patch("bookwyrm.connectors.inventaire.get_data") as get_data_mock: + get_data_mock.return_value = edition_data + formatted = self.connector.get_book_data("hi") + self.assertFalse(self.connector.is_work_data(formatted)) + + @responses.activate + def test_get_edition_from_work_data(self): + """load edition""" + responses.add( + responses.GET, + "https://inventaire.io/?action=by-uris&uris=hello", + json={"entities": {}}, + ) + data = {"uri": "blah"} + with patch( + "bookwyrm.connectors.inventaire.Connector.load_edition_data" + ) as loader_mock, patch( + "bookwyrm.connectors.inventaire.Connector.get_book_data" + ) as getter_mock: + loader_mock.return_value = {"uris": ["hello"]} + self.connector.get_edition_from_work_data(data) + self.assertTrue(getter_mock.called) + + with patch( + "bookwyrm.connectors.inventaire.Connector.load_edition_data" + ) as loader_mock: + loader_mock.return_value = {"uris": []} + with self.assertRaises(ConnectorException): + self.connector.get_edition_from_work_data(data) + + @responses.activate + def test_get_work_from_edition_data(self): + """load work""" + responses.add( + responses.GET, + "https://inventaire.io/?action=by-uris&uris=hello", + ) + data = {"wdt:P629": "hello"} + self.connector.get_work_from_edition_data(data) + + data = {"wdt:P629": None} + with self.assertRaises(ConnectorException): + self.connector.get_work_from_edition_data(data) + def test_get_language_code(self): """get english or whatever is in reach""" options = { From d3e4c7e8d9c8c1cf98e07bafd9108553aa90551d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 27 Oct 2021 10:40:37 -0700 Subject: [PATCH 003/217] Removes change to boolean logic --- bookwyrm/connectors/inventaire.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bookwyrm/connectors/inventaire.py b/bookwyrm/connectors/inventaire.py index 43aee2f43..e180dc62f 100644 --- a/bookwyrm/connectors/inventaire.py +++ b/bookwyrm/connectors/inventaire.py @@ -104,7 +104,9 @@ class Connector(AbstractConnector): def parse_isbn_search_data(self, data): """got some daaaata""" - results = data.get("entities", []) + results = data.get("entities") + if not results: + return [] return list(results.values()) def format_isbn_search_result(self, search_result): From 625cfac76fb67eae352d74f05484ce4f87d9a04a Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Fri, 29 Oct 2021 16:12:31 +1100 Subject: [PATCH 004/217] isni author lookup utility --- bookwyrm/utils/isni.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 bookwyrm/utils/isni.py diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py new file mode 100644 index 000000000..2fd87bebc --- /dev/null +++ b/bookwyrm/utils/isni.py @@ -0,0 +1,39 @@ +import requests +import xml.etree.ElementTree as ET + +# get data +base_string = "http://isni.oclc.org/sru/?query=pica.na+%3D+%22" +suffix_string = "%22&version=1.1&operation=searchRetrieve&recordSchema=isni-b&maximumRecords=10&startRecord=1&recordPacking=xml&sortKeys=RLV%2Cpica%2C0%2C%2C" + + +def url_stringify(string): + return string.replace(" ", "+") + + +def find_authors_by_name(names): + + names = url_stringify(names) + query = base_string + names + suffix_string + r = requests.get(query) + # parse xml + payload = r.text + root = ET.fromstring(payload) + + # build list of possible authors + possible_authors = [] + for el in root.iter("responseRecord"): + + author = dict() + author["uri"] = el.find(".//isniURI").text + # NOTE: this will often be incorrect, some naming systems list "surname" before personal name + personal_name = el.find(".//forename/..") + forename = personal_name.find(".//forename") + surname = personal_name.find(".//surname") + author["name"] = surname.text + if personal_name: + author["name"] = forename.text + " " + surname.text + author["description"] = el.find(".//nameTitle").text + + possible_authors.append(author) + + return possible_authors From f2e4865adf1df01a1d1bbe9c096f25c5d8f2d712 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Fri, 29 Oct 2021 16:13:05 +1100 Subject: [PATCH 005/217] check isni sources when editing book authors --- bookwyrm/templates/book/edit/edit_book.html | 18 ++++++++++++++++++ bookwyrm/views/books/edit_book.py | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/book/edit/edit_book.html b/bookwyrm/templates/book/edit/edit_book.html index fc11208fd..0854a8790 100644 --- a/bookwyrm/templates/book/edit/edit_book.html +++ b/bookwyrm/templates/book/edit/edit_book.html @@ -50,6 +50,24 @@
{% for author in author_matches %} + {% if author.isni_matches %} +
+ + {% blocktrans with name=author.name %}Is "{{ name }}" one of these?{% endblocktrans %} + + {% with forloop.counter0 as counter %} + {% for match in author.isni_matches %} + + {% endfor %} + {% endwith %} +
+ {% endif %}
{% blocktrans with name=author.name %}Is "{{ name }}" an existing author?{% endblocktrans %} diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index 1445dc011..ed704e1e0 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -13,7 +13,7 @@ from django.views import View from bookwyrm import book_search, forms, models from bookwyrm.views.helpers import get_edition from .books import set_cover_from_url - +from bookwyrm.utils.isni import find_authors_by_name # pylint: disable=no-self-use @method_decorator(login_required, name="dispatch") @@ -48,6 +48,7 @@ class EditBook(View): if add_author: data["add_author"] = add_author data["author_matches"] = [] + data["isni_matches"] = [] for author in add_author.split(","): if not author: continue @@ -65,6 +66,9 @@ class EditBook(View): .filter(rank__gt=0.4) .order_by("-rank")[:5] ), + "isni_matches": find_authors_by_name( + author + ), # find matches from ISNI API } ) From d87e1b1567da7d6990bc586289246974abdfaa06 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Fri, 29 Oct 2021 21:00:35 +1100 Subject: [PATCH 006/217] fix encoding The OCLC server claims that the xml payload is encoded as latin1 (ISO-8859-1). This causes Requests to incorrectly encode things as latin1, when actually everything is (thank goodness) UTF-8. We can fix it by just telling Requests that it is really UTF-8 With thanks to Tex Texin, creator of http://i18nqa.com/debug/utf8-debug.html --- bookwyrm/utils/isni.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index 2fd87bebc..c905eb1c2 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -1,5 +1,6 @@ import requests import xml.etree.ElementTree as ET +from xml.etree.ElementTree import XMLParser # get data base_string = "http://isni.oclc.org/sru/?query=pica.na+%3D+%22" @@ -15,8 +16,11 @@ def find_authors_by_name(names): names = url_stringify(names) query = base_string + names + suffix_string r = requests.get(query) - # parse xml + # the OCLC ISNI server asserts the payload is encoded + # in latin1, but we know better + r.encoding = "utf-8" payload = r.text + # parse xml root = ET.fromstring(payload) # build list of possible authors From 87ed6f8380c8588cf9a24a5a1e7176fcffb57a28 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Fri, 29 Oct 2021 21:14:32 +1100 Subject: [PATCH 007/217] code formatting --- bookwyrm/templates/book/edit/edit_book.html | 2 +- bookwyrm/utils/isni.py | 29 +++++++++++---------- bookwyrm/views/books/edit_book.py | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/bookwyrm/templates/book/edit/edit_book.html b/bookwyrm/templates/book/edit/edit_book.html index 0854a8790..3d79bed85 100644 --- a/bookwyrm/templates/book/edit/edit_book.html +++ b/bookwyrm/templates/book/edit/edit_book.html @@ -63,7 +63,7 @@ {{ match.description }} - + {% endfor %} {% endwith %}
diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index c905eb1c2..e12c3d721 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -1,42 +1,43 @@ -import requests +"""ISNI author checking utilities""" import xml.etree.ElementTree as ET -from xml.etree.ElementTree import XMLParser +import requests # get data -base_string = "http://isni.oclc.org/sru/?query=pica.na+%3D+%22" -suffix_string = "%22&version=1.1&operation=searchRetrieve&recordSchema=isni-b&maximumRecords=10&startRecord=1&recordPacking=xml&sortKeys=RLV%2Cpica%2C0%2C%2C" +BASE_STRING = "http://isni.oclc.org/sru/?query=pica.na+%3D+%22" +SUFFIX_STRING = "%22&version=1.1&operation=searchRetrieve&recordSchema=isni-b&maximumRecords=10&startRecord=1&recordPacking=xml&sortKeys=RLV%2Cpica%2C0%2C%2C" def url_stringify(string): + """replace spaces for url encoding""" return string.replace(" ", "+") def find_authors_by_name(names): - + """Query the ISNI database for an author""" names = url_stringify(names) - query = base_string + names + suffix_string - r = requests.get(query) + query = BASE_STRING + names + SUFFIX_STRING + result = requests.get(query) # the OCLC ISNI server asserts the payload is encoded # in latin1, but we know better - r.encoding = "utf-8" - payload = r.text + result.encoding = "utf-8" + payload = result.text # parse xml root = ET.fromstring(payload) # build list of possible authors possible_authors = [] - for el in root.iter("responseRecord"): + for element in root.iter("responseRecord"): - author = dict() - author["uri"] = el.find(".//isniURI").text + author = {} + author["uri"] = element.find(".//isniURI").text # NOTE: this will often be incorrect, some naming systems list "surname" before personal name - personal_name = el.find(".//forename/..") + personal_name = element.find(".//forename/..") forename = personal_name.find(".//forename") surname = personal_name.find(".//surname") author["name"] = surname.text if personal_name: author["name"] = forename.text + " " + surname.text - author["description"] = el.find(".//nameTitle").text + author["description"] = element.find(".//nameTitle").text possible_authors.append(author) diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index ed704e1e0..cbfb21f10 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -11,9 +11,9 @@ from django.utils.decorators import method_decorator from django.views import View from bookwyrm import book_search, forms, models +from bookwyrm.utils.isni import find_authors_by_name from bookwyrm.views.helpers import get_edition from .books import set_cover_from_url -from bookwyrm.utils.isni import find_authors_by_name # pylint: disable=no-self-use @method_decorator(login_required, name="dispatch") From 45158a1c03727e708c9632450555c73202a4a9f7 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sat, 30 Oct 2021 09:24:42 +1100 Subject: [PATCH 008/217] improve isni search logic - skip ISNIs that aren't persons - don't look for text values in non-existent nameTitle elements --- bookwyrm/utils/isni.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index e12c3d721..f3bb7b5ce 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -4,6 +4,7 @@ import requests # get data BASE_STRING = "http://isni.oclc.org/sru/?query=pica.na+%3D+%22" +#pylint: disable=line-too-long SUFFIX_STRING = "%22&version=1.1&operation=searchRetrieve&recordSchema=isni-b&maximumRecords=10&startRecord=1&recordPacking=xml&sortKeys=RLV%2Cpica%2C0%2C%2C" @@ -30,14 +31,16 @@ def find_authors_by_name(names): author = {} author["uri"] = element.find(".//isniURI").text - # NOTE: this will often be incorrect, some naming systems list "surname" before personal name + # NOTE: this will often be incorrect, many naming systems + # list "surname" before personal name personal_name = element.find(".//forename/..") - forename = personal_name.find(".//forename") - surname = personal_name.find(".//surname") - author["name"] = surname.text + description = element.find(".//nameTitle") if personal_name: + forename = personal_name.find(".//forename") + surname = personal_name.find(".//surname") author["name"] = forename.text + " " + surname.text - author["description"] = element.find(".//nameTitle").text + if description is not None: + author["description"] = description.text possible_authors.append(author) From bce5f3f3b50725ba583d3fc1a72732eb84fde415 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 31 Oct 2021 17:58:15 +1100 Subject: [PATCH 009/217] populate new authors with isni data If a user selects an author pulled from the ISNI service when editing a book, use any relevant data from ISNI to populate the new author record. This includes - bio - aliases - isni - wikipedia url - viaf --- bookwyrm/templates/book/edit/edit_book.html | 34 +++--- bookwyrm/utils/isni.py | 119 ++++++++++++++++---- bookwyrm/views/books/edit_book.py | 13 ++- 3 files changed, 119 insertions(+), 47 deletions(-) diff --git a/bookwyrm/templates/book/edit/edit_book.html b/bookwyrm/templates/book/edit/edit_book.html index 3d79bed85..104cef4df 100644 --- a/bookwyrm/templates/book/edit/edit_book.html +++ b/bookwyrm/templates/book/edit/edit_book.html @@ -50,39 +50,33 @@
{% for author in author_matches %} - {% if author.isni_matches %}
- {% blocktrans with name=author.name %}Is "{{ name }}" one of these?{% endblocktrans %} + {% blocktrans with name=author.name %}Is "{{ name }}" one of these authors?{% endblocktrans %} {% with forloop.counter0 as counter %} - {% for match in author.isni_matches %} -
- {% endif %} -
- - {% blocktrans with name=author.name %}Is "{{ name }}" an existing author?{% endblocktrans %} - - {% with forloop.counter0 as counter %} + {% endif %} {% for match in author.matches %} -
{% endif %}
- - - {% trans "Separate multiple values with commas." %} + + {% for author in add_author %} + + + {% empty %} + + + {% endfor %}
+ {% trans "Add Another Author" %}
diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index 1445dc011..0bacd6074 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -43,12 +43,12 @@ class EditBook(View): if not form.is_valid(): return TemplateResponse(request, "book/edit/edit_book.html", data) - add_author = request.POST.get("add_author") + add_author = request.POST.getlist("add_author") # we're adding an author through a free text field if add_author: data["add_author"] = add_author data["author_matches"] = [] - for author in add_author.split(","): + for author in add_author: if not author: continue # check for existing authors From a0093a8a2e63c42fa89e09c0d1061b8e4f41dda5 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 22 Nov 2021 00:25:47 +0100 Subject: [PATCH 069/217] Add status type filters --- bookwyrm/forms.py | 23 ++++++++++++ bookwyrm/models/user.py | 9 ++++- bookwyrm/templates/feed/feed.html | 21 +++++++++++ .../widgets/checkbox_select_horizontal.html | 11 ++++++ .../checkbox_select_horizontal_option.html | 4 +++ bookwyrm/views/feed.py | 35 +++++++++++++++++-- 6 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 bookwyrm/templates/widgets/checkbox_select_horizontal.html create mode 100644 bookwyrm/templates/widgets/checkbox_select_horizontal_option.html diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 847ca05c0..fc8f018d0 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -174,6 +174,29 @@ class UserGroupForm(CustomForm): fields = ["groups"] +class CheckboxSelectMultipleHorizontal(widgets.CheckboxSelectMultiple): + template_name = "widgets/checkbox_select_horizontal.html" + option_template_name = "widgets/checkbox_select_horizontal_option.html" + + +class FeedStatusTypes(CustomForm): + class Meta: + model = models.User + fields = ["feed_status_types"] + help_texts = {f: None for f in fields} + labels = {"feed_status_types": ""} + widgets = { + "feed_status_types": CheckboxSelectMultipleHorizontal( + choices=[ + ("review", _("Reviews")), + ("comment", _("Comments")), + ("quotation", _("Quotations")), + ("everything", _("Everything else")), + ], + ), + } + + class CoverForm(CustomForm): class Meta: model = models.Book diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index d7945843f..7ca92e4f2 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -4,7 +4,7 @@ from urllib.parse import urlparse from django.apps import apps from django.contrib.auth.models import AbstractUser, Group -from django.contrib.postgres.fields import CICharField +from django.contrib.postgres.fields import ArrayField, CICharField from django.core.validators import MinValueValidator from django.dispatch import receiver from django.db import models, transaction @@ -128,6 +128,13 @@ class User(OrderedCollectionPageMixin, AbstractUser): show_suggested_users = models.BooleanField(default=True) discoverable = fields.BooleanField(default=False) + # feed options + feed_status_types = ArrayField( + models.CharField(max_length=10, blank=False), + size=8, + default=list(["review", "comment", "quotation", "everything"]), + ) + preferred_timezone = models.CharField( choices=[(str(tz), str(tz)) for tz in pytz.all_timezones], default=str(pytz.utc), diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index a6175199d..9783e2126 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -16,6 +16,27 @@ + +
+ + What to display? + {% if settings_saved %} + Saved! + {% endif %} + + + {% csrf_token %} +
+ {{ feed_status_types_form }} +
+
+ +
+ +
+ {# announcements and system messages #} {% if not activities.number > 1 %} {% trans "Author of " %}{{ book_title }} {% else %} - {% trans "Author of " %}{{ alt_title }} + {% if alt_title %}{% trans "Author of " %}{{ alt_title }}{% else %} {% trans "Find more information at isni.org" %}{% endif %} {% endif %} {% endwith %}

diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index fead999a9..fd0dc0835 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -92,32 +92,34 @@ def find_authors_by_name(name_string, description=False): # build list of possible authors possible_authors = [] for element in root.iter("responseRecord"): - personal_name = element.find(".//forename/..") - bio = element.find(".//nameTitle") - if not personal_name: continue author = get_author_from_isni(element.find(".//isniUnformatted").text) if bool(description): - titles = element.findall(".//title") - if titles: - # some of the "titles" in ISNI are a little ...iffy - title_element = [e for e in titles if not e.text.replace('@', '').isnumeric()][0] - title = ( - title_element.text.replace('@', '') - if titles is not None - and title_element is not None - and len(title_element.text) > 4 - else None - ) - author.bio = ( - title if title is not None - else bio.text if bio is not None - else "More information at isni.org" - ) + + titles = [] + # prefer title records from LoC+ coop, Australia, Ireland, or Singapore + # in that order + for source in ["LCNACO", "NLA", "N6I", "NLB"]: + for parent in element.findall(f'.//titleOfWork/[@source="{source}"]'): + titles.append(parent.find(".//title")) + for parent in element.findall(f'.//titleOfWork[@subsource="{source}"]'): + titles.append(parent.find(".//title")) + # otherwise just grab the first title listing + titles.append(element.find(".//title")) + + if titles is not None: + # some of the "titles" in ISNI are a little ...iffy + # '@' is used by ISNI/OCLC to index the starting point ignoring stop words + # (e.g. "The @Government of no one") + title_elements = [e for e in titles if not e.text.replace('@', '').isnumeric()] + if len(title_elements): + author.bio = title_elements[0].text.replace('@', '') + else: + author.bio = None possible_authors.append(author) From a9d921cc065a9e7017ad93b244ea0bbe2eee7ea3 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 22 Nov 2021 12:52:59 +1100 Subject: [PATCH 073/217] code cleanup --- bookwyrm/templatetags/utilities.py | 2 +- bookwyrm/utils/isni.py | 53 +++++++++++++++--------------- bookwyrm/views/books/edit_book.py | 13 ++++---- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/bookwyrm/templatetags/utilities.py b/bookwyrm/templatetags/utilities.py index dc5d52208..5cc25fed8 100644 --- a/bookwyrm/templatetags/utilities.py +++ b/bookwyrm/templatetags/utilities.py @@ -92,7 +92,7 @@ def get_isni(existing, author, autoescape=True): if len(existing) == 0: return "" for value in existing: - if hasattr(value, "isni")and auth_isni == re.sub(r"\D", "", str(value.isni)): + if hasattr(value, "isni") and auth_isni == re.sub(r"\D", "", str(value.isni)): isni = value.isni return mark_safe( f'' diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index fd0dc0835..952a22acd 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -4,6 +4,7 @@ import requests from bookwyrm import activitypub, models + def request_isni_data(search_index, search_term, max_records=5): """Request data from the ISNI API""" @@ -18,11 +19,7 @@ def request_isni_data(search_index, search_term, max_records=5): "recordPacking": "xml", "sortKeys": "RLV,pica,0,,", } - result = requests.get( - "http://isni.oclc.org/sru/", - params=query_params, - timeout=10 - ) + result = requests.get("http://isni.oclc.org/sru/", params=query_params, timeout=10) # the OCLC ISNI server asserts the payload is encoded # in latin1, but we know better result.encoding = "utf-8" @@ -58,10 +55,9 @@ def get_other_identifier(element, code): for source in element.findall(".//sources"): code_of_source = source.find(".//codeOfSource") if ( - code_of_source is not None - and code_of_source.text == code.upper() - or code_of_source.text == code.lower() - ): + code_of_source is not None + and code_of_source.text.lower() == code.lower() + ): return source.find(".//sourceIdentifier").text return "" @@ -75,10 +71,10 @@ def get_external_information_uri(element, match_string): information = source.find(".//information") uri = source.find(".//URI") if ( - uri is not None - and information is not None - and information.text.lower() == match_string.lower() - ): + uri is not None + and information is not None + and information.text.lower() == match_string.lower() + ): return uri.text return "" @@ -112,12 +108,14 @@ def find_authors_by_name(name_string, description=False): titles.append(element.find(".//title")) if titles is not None: - # some of the "titles" in ISNI are a little ...iffy - # '@' is used by ISNI/OCLC to index the starting point ignoring stop words + # some of the "titles" in ISNI are a little ...iffy + # '@' is used by ISNI/OCLC to index the starting point ignoring stop words # (e.g. "The @Government of no one") - title_elements = [e for e in titles if not e.text.replace('@', '').isnumeric()] + title_elements = [ + e for e in titles if not e.text.replace("@", "").isnumeric() + ] if len(title_elements): - author.bio = title_elements[0].text.replace('@', '') + author.bio = title_elements[0].text.replace("@", "") else: author.bio = None @@ -149,24 +147,25 @@ def get_author_from_isni(isni): wikipedia = get_external_information_uri(element, "Wikipedia") author = activitypub.Author( - id=element.find(".//isniURI").text, - name=name, - isni=isni, - viafId=viaf, - aliases=aliases, - bio=bio, - wikipediaLink=wikipedia + id=element.find(".//isniURI").text, + name=name, + isni=isni, + viafId=viaf, + aliases=aliases, + bio=bio, + wikipediaLink=wikipedia, ) return author + def build_author_from_isni(match_value): - """Build dict with basic author details from ISNI or author name""" + """Build basic author class object from ISNI URL""" # if it is an isni value get the data if match_value.startswith("https://isni.org/isni/"): isni = match_value.replace("https://isni.org/isni/", "") - return { "author": get_author_from_isni(isni) } + return {"author": get_author_from_isni(isni)} # otherwise it's a name string return {} @@ -177,7 +176,7 @@ def augment_author_metadata(author, isni): isni_author = get_author_from_isni(isni) isni_author.to_model(model=models.Author, instance=author, overwrite=False) - # we DO want to overwrite aliases because we're adding them to the + # we DO want to overwrite aliases because we're adding them to the # existing aliases and ISNI will usually have more. # We need to dedupe because ISNI records often have lots of dupe aliases aliases = set(isni_author.aliases) diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index 3098e977b..93932a351 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -12,6 +12,7 @@ from django.utils.decorators import method_decorator from django.views import View from bookwyrm import book_search, forms, models + # from bookwyrm.activitypub.base_activity import ActivityObject from bookwyrm.utils.isni import ( find_authors_by_name, @@ -72,8 +73,7 @@ class EditBook(View): ) isni_authors = find_authors_by_name( - author, - description=True + author, description=True ) # find matches from ISNI API # dedupe isni authors we already have in the DB @@ -187,12 +187,11 @@ class ConfirmEditBook(View): author_object = build_author_from_isni(isni_match) # with author data class from isni id if "author" in author_object: - # TESTING - skeleton = models.Author.objects.create(name=author_object["author"].name) + skeleton = models.Author.objects.create( + name=author_object["author"].name + ) author = author_object["author"].to_model( - model=models.Author, - overwrite=True, - instance=skeleton + model=models.Author, overwrite=True, instance=skeleton ) else: # or it's just a name From d8e83ffe82a4568bb500d3fa37ae6b9718f415a8 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 22 Nov 2021 13:01:58 +1100 Subject: [PATCH 074/217] moar code linting --- bookwyrm/utils/isni.py | 7 +------ bookwyrm/views/books/edit_book.py | 1 + 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index 952a22acd..a35c3f249 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -54,10 +54,7 @@ def get_other_identifier(element, code): # try sources for source in element.findall(".//sources"): code_of_source = source.find(".//codeOfSource") - if ( - code_of_source is not None - and code_of_source.text.lower() == code.lower() - ): + if code_of_source is not None and code_of_source.text.lower() == code.lower(): return source.find(".//sourceIdentifier").text return "" @@ -184,5 +181,3 @@ def augment_author_metadata(author, isni): aliases.add(alias) author.aliases = list(aliases) author.save() - - return diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index 93932a351..fc13aa6c4 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -152,6 +152,7 @@ class ConfirmEditBook(View): """confirm edits to a book""" # pylint: disable=too-many-locals + # pylint: disable=too-many-branches def post(self, request, book_id=None): """edit a book cool""" # returns None if no match is found From 47cfc2f157e6dce13f33709e26d4914ba35aab39 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 22 Nov 2021 18:52:57 +0100 Subject: [PATCH 075/217] Hardcode form --- bookwyrm/forms.py | 9 ++----- bookwyrm/templates/feed/feed.html | 27 ++++++++++++++----- .../widgets/checkbox_select_horizontal.html | 11 -------- .../checkbox_select_horizontal_option.html | 4 --- bookwyrm/views/feed.py | 12 ++++++--- 5 files changed, 30 insertions(+), 33 deletions(-) delete mode 100644 bookwyrm/templates/widgets/checkbox_select_horizontal.html delete mode 100644 bookwyrm/templates/widgets/checkbox_select_horizontal_option.html diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index fc8f018d0..f52cbeb31 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -174,19 +174,14 @@ class UserGroupForm(CustomForm): fields = ["groups"] -class CheckboxSelectMultipleHorizontal(widgets.CheckboxSelectMultiple): - template_name = "widgets/checkbox_select_horizontal.html" - option_template_name = "widgets/checkbox_select_horizontal_option.html" - - -class FeedStatusTypes(CustomForm): +class FeedStatusTypesForm(CustomForm): class Meta: model = models.User fields = ["feed_status_types"] help_texts = {f: None for f in fields} labels = {"feed_status_types": ""} widgets = { - "feed_status_types": CheckboxSelectMultipleHorizontal( + "feed_status_types": widgets.CheckboxSelectMultiple( choices=[ ("review", _("Reviews")), ("comment", _("Comments")), diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 9783e2126..14df11c68 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -16,22 +16,35 @@ - +{# feed settings #}
- What to display? + + {{ _("Feed settings") }} + {% if settings_saved %} - Saved! + {{ _("Saved!") }} {% endif %} -
+ {% csrf_token %} +
- {{ feed_status_types_form }} +
+
+ + {% for name, value in feed_status_types_options %} + + {% endfor %} +
+
@@ -56,7 +69,7 @@ {# activity feed #} {% if not activities %}
-

{% trans "There aren't any activities right now! Try following a user to get started" %}

+

{% trans "There aren't any activities right now! Try following a user to get started" %}{% if user.feed_status_types|length < 4 %}{% trans ", or enable more status types" %}{% endif %}

{% if request.user.show_suggested_users and suggested_users %} {# suggested users for when things are very lonely #} diff --git a/bookwyrm/templates/widgets/checkbox_select_horizontal.html b/bookwyrm/templates/widgets/checkbox_select_horizontal.html deleted file mode 100644 index d040df492..000000000 --- a/bookwyrm/templates/widgets/checkbox_select_horizontal.html +++ /dev/null @@ -1,11 +0,0 @@ -{% with id=widget.attrs.id %} - -
- {% for group, options, index in widget.optgroups %} - {% for option in options %} - {% include option.template_name with widget=option %} - {% endfor %} - {% endfor %} -
-
-{% endwith %} diff --git a/bookwyrm/templates/widgets/checkbox_select_horizontal_option.html b/bookwyrm/templates/widgets/checkbox_select_horizontal_option.html deleted file mode 100644 index 03c688d53..000000000 --- a/bookwyrm/templates/widgets/checkbox_select_horizontal_option.html +++ /dev/null @@ -1,4 +0,0 @@ - - {% include "django/forms/widgets/input.html" %} - {{ widget.label }} - diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 165e662fc..0002448e4 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -7,6 +7,7 @@ from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse from django.utils import timezone from django.utils.decorators import method_decorator +from django.utils.translation import gettext_lazy as _ from django.views import View from bookwyrm import activitystreams, forms, models @@ -25,7 +26,7 @@ class Feed(View): def post(self, request, tab): """save feed settings form, with a silent validation fail""" settings_saved = False - form = forms.FeedStatusTypes(request.POST, instance=request.user) + form = forms.FeedStatusTypesForm(request.POST, instance=request.user) if form.is_valid(): form.save() settings_saved = True @@ -57,9 +58,12 @@ class Feed(View): "tab": tab, "streams": STREAMS, "goal_form": forms.GoalForm(), - "feed_status_types_form": forms.FeedStatusTypes( - instance=request.user, - ), + "feed_status_types_options": [ + ("review", _("Reviews")), + ("comment", _("Comments")), + ("quotation", _("Quotations")), + ("everything", _("Everything else")), + ], "settings_saved": settings_saved, "path": f"/{tab['key']}", }, From 63e284dc4114331549337fcd33994d987f0938ac Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 22 Nov 2021 18:59:46 +0100 Subject: [PATCH 076/217] Forgive me pylint --- bookwyrm/views/feed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 0002448e4..3ac3f5914 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -255,10 +255,10 @@ def get_suggested_books(user, max_books=5): def filter_stream_by_status_type(activities, allowed_types=None): + """filter out activities based on types""" if not allowed_types: allowed_types = [] - """filter out activities based on types""" if "review" not in allowed_types: activities = activities.filter(Q(review__isnull=True)) if "comment" not in allowed_types: From 7bdfacb6888b328c00b013ce0f55e339d14bc994 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 22 Nov 2021 19:25:49 +0100 Subject: [PATCH 077/217] Add translation keys --- locale/en_US/LC_MESSAGES/django.po | 85 +++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 20 deletions(-) diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index f5df1265d..0237d1a8a 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-17 18:03+0000\n" +"POT-Creation-Date: 2021-11-22 18:23+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -18,58 +18,75 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:248 +#: bookwyrm/forms.py:186 bookwyrm/templates/book/book.html:218 +#: bookwyrm/views/feed.py:62 +msgid "Reviews" +msgstr "" + +#: bookwyrm/forms.py:187 bookwyrm/views/feed.py:63 +msgid "Comments" +msgstr "" + +#: bookwyrm/forms.py:188 bookwyrm/views/feed.py:64 +msgid "Quotations" +msgstr "" + +#: bookwyrm/forms.py:189 bookwyrm/views/feed.py:65 +msgid "Everything else" +msgstr "" + +#: bookwyrm/forms.py:266 msgid "A user with this email already exists." msgstr "" -#: bookwyrm/forms.py:262 +#: bookwyrm/forms.py:280 msgid "One Day" msgstr "" -#: bookwyrm/forms.py:263 +#: bookwyrm/forms.py:281 msgid "One Week" msgstr "" -#: bookwyrm/forms.py:264 +#: bookwyrm/forms.py:282 msgid "One Month" msgstr "" -#: bookwyrm/forms.py:265 +#: bookwyrm/forms.py:283 msgid "Does Not Expire" msgstr "" -#: bookwyrm/forms.py:269 +#: bookwyrm/forms.py:287 #, python-brace-format msgid "{i} uses" msgstr "" -#: bookwyrm/forms.py:270 +#: bookwyrm/forms.py:288 msgid "Unlimited" msgstr "" -#: bookwyrm/forms.py:338 +#: bookwyrm/forms.py:356 msgid "List Order" msgstr "" -#: bookwyrm/forms.py:339 +#: bookwyrm/forms.py:357 msgid "Book Title" msgstr "" -#: bookwyrm/forms.py:340 bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/forms.py:358 bookwyrm/templates/shelf/shelf.html:149 #: bookwyrm/templates/shelf/shelf.html:181 #: bookwyrm/templates/snippets/create_status/review.html:33 msgid "Rating" msgstr "" -#: bookwyrm/forms.py:342 bookwyrm/templates/lists/list.html:110 +#: bookwyrm/forms.py:360 bookwyrm/templates/lists/list.html:110 msgid "Sort By" msgstr "" -#: bookwyrm/forms.py:346 +#: bookwyrm/forms.py:364 msgid "Ascending" msgstr "" -#: bookwyrm/forms.py:347 +#: bookwyrm/forms.py:365 msgid "Descending" msgstr "" @@ -445,10 +462,6 @@ msgstr "" msgid "You don't have any reading activity for this book." msgstr "" -#: bookwyrm/templates/book/book.html:218 -msgid "Reviews" -msgstr "" - #: bookwyrm/templates/book/book.html:223 msgid "Your reviews" msgstr "" @@ -1016,6 +1029,22 @@ msgstr "" msgid "Learn more about %(site_name)s:" msgstr "" +#: bookwyrm/templates/email/moderation_report/html_content.html:6 +#: bookwyrm/templates/email/moderation_report/text_content.html:5 +#, python-format +msgid "@%(reporter)s has flagged behavior by @%(reportee)s for moderation. " +msgstr "" + +#: bookwyrm/templates/email/moderation_report/html_content.html:9 +#: bookwyrm/templates/email/moderation_report/text_content.html:7 +msgid "View report" +msgstr "" + +#: bookwyrm/templates/email/moderation_report/subject.html:2 +#, python-format +msgid "New report for %(site_name)s" +msgstr "" + #: bookwyrm/templates/email/password_reset/html_content.html:6 #: bookwyrm/templates/email/password_reset/text_content.html:4 #, python-format @@ -1058,15 +1087,31 @@ msgstr "" msgid "You have no messages right now." msgstr "" -#: bookwyrm/templates/feed/feed.html:22 +#: bookwyrm/templates/feed/feed.html:23 +msgid "Feed settings" +msgstr "" + +#: bookwyrm/templates/feed/feed.html:26 +msgid "Saved!" +msgstr "" + +#: bookwyrm/templates/feed/feed.html:47 +msgid "Save settings" +msgstr "" + +#: bookwyrm/templates/feed/feed.html:56 #, python-format msgid "load 0 unread status(es)" msgstr "" -#: bookwyrm/templates/feed/feed.html:38 +#: bookwyrm/templates/feed/feed.html:72 msgid "There aren't any activities right now! Try following a user to get started" msgstr "" +#: bookwyrm/templates/feed/feed.html:72 +msgid ", or enable more status types" +msgstr "" + #: bookwyrm/templates/feed/goal_card.html:6 #: bookwyrm/templates/feed/layout.html:90 #: bookwyrm/templates/user/goal_form.html:6 From 8752fec37f3b052c7d96d78ff1a970152e84ae9f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 23 Nov 2021 12:38:02 -0800 Subject: [PATCH 078/217] Updates for Spanish, Galician, French, Lithuanian locales --- locale/de_DE/LC_MESSAGES/django.mo | Bin 60544 -> 30883 bytes locale/es_ES/LC_MESSAGES/django.mo | Bin 60011 -> 64050 bytes locale/es_ES/LC_MESSAGES/django.po | 70 +++++----- locale/fr_FR/LC_MESSAGES/django.mo | Bin 65002 -> 44850 bytes locale/fr_FR/LC_MESSAGES/django.po | 16 +-- locale/gl_ES/LC_MESSAGES/django.mo | Bin 55932 -> 62651 bytes locale/gl_ES/LC_MESSAGES/django.po | 200 +++++++++++++-------------- locale/lt_LT/LC_MESSAGES/django.mo | Bin 61847 -> 65147 bytes locale/lt_LT/LC_MESSAGES/django.po | 72 +++++----- locale/zh_Hans/LC_MESSAGES/django.mo | Bin 56164 -> 44096 bytes locale/zh_Hant/LC_MESSAGES/django.mo | Bin 37625 -> 38839 bytes 11 files changed, 179 insertions(+), 179 deletions(-) diff --git a/locale/de_DE/LC_MESSAGES/django.mo b/locale/de_DE/LC_MESSAGES/django.mo index fe402ad72b85652f0f99396feb4ce8486ff03152..4ce83f72b3f3850c58528f13afcd23442a75a515 100644 GIT binary patch delta 14999 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 Bt}57^E2(7!sWs7>pPg7;2p%`ZhQ-Fo-cQFx+-# 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 CO_%JXqO!Z)35Mf|ocm$RI?!mwy%fP_E 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 G5(NO;MK>$} delta 17483 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\n" "Language-Team: Spanish\n" "Language: es\n" @@ -184,7 +184,7 @@ msgstr "Español" #: bookwyrm/settings.py:168 msgid "Galego (Galician)" -msgstr "" +msgstr "Gallego (Galicia)" #: bookwyrm/settings.py:169 msgid "Français (French)" @@ -192,7 +192,7 @@ msgstr "Français (Francés)" #: bookwyrm/settings.py:170 msgid "Lietuvių (Lithuanian)" -msgstr "" +msgstr "Lituano (Lituania)" #: bookwyrm/settings.py:171 msgid "Português - Brasil (Brazilian Portuguese)" @@ -904,17 +904,17 @@ msgstr "Todos los usuarios conocidos" #: bookwyrm/templates/discover/card-header.html:8 #, python-format msgid "%(username)s wants to read %(book_title)s" -msgstr "" +msgstr "%(username)s quiere leer %(book_title)s" #: bookwyrm/templates/discover/card-header.html:13 #, python-format msgid "%(username)s finished reading %(book_title)s" -msgstr "" +msgstr "%(username)s ha terminado de leer %(book_title)s" #: bookwyrm/templates/discover/card-header.html:18 #, python-format msgid "%(username)s started reading %(book_title)s" -msgstr "" +msgstr "%(username)s ha empezado a leer %(book_title)s" #: bookwyrm/templates/discover/card-header.html:23 #, python-format @@ -1400,11 +1400,11 @@ msgstr "Importar estado" #: bookwyrm/templates/import/import_status.html:13 #: bookwyrm/templates/import/import_status.html:27 msgid "Retry Status" -msgstr "" +msgstr "Estado del Reintento" #: bookwyrm/templates/import/import_status.html:22 msgid "Imports" -msgstr "" +msgstr "Importaciones" #: bookwyrm/templates/import/import_status.html:39 msgid "Import started:" @@ -1412,38 +1412,38 @@ msgstr "Importación ha empezado:" #: bookwyrm/templates/import/import_status.html:48 msgid "In progress" -msgstr "" +msgstr "En progreso" #: bookwyrm/templates/import/import_status.html:50 msgid "Refresh" -msgstr "" +msgstr "Refrescar" #: bookwyrm/templates/import/import_status.html:71 #, python-format msgid "%(display_counter)s item needs manual approval." msgid_plural "%(display_counter)s items need manual approval." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(display_counter)s elemento necesita aprobación manual." +msgstr[1] "%(display_counter)s elementos necesitan aprobación manual." #: bookwyrm/templates/import/import_status.html:76 #: bookwyrm/templates/import/manual_review.html:8 msgid "Review items" -msgstr "" +msgstr "Revisar elementos" #: bookwyrm/templates/import/import_status.html:82 #, python-format msgid "%(display_counter)s item failed to import." msgid_plural "%(display_counter)s items failed to import." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(display_counter)s elemento no se pudo importar." +msgstr[1] "%(display_counter)s elementos no se pudieron importar." #: bookwyrm/templates/import/import_status.html:88 msgid "View and troubleshoot failed items" -msgstr "" +msgstr "Ver y solucionar los elementos fallidos" #: bookwyrm/templates/import/import_status.html:100 msgid "Row" -msgstr "" +msgstr "Fila" #: bookwyrm/templates/import/import_status.html:103 #: bookwyrm/templates/shelf/shelf.html:141 @@ -1453,7 +1453,7 @@ msgstr "Título" #: bookwyrm/templates/import/import_status.html:106 msgid "ISBN" -msgstr "" +msgstr "ISBN" #: bookwyrm/templates/import/import_status.html:109 #: bookwyrm/templates/shelf/shelf.html:142 @@ -1463,7 +1463,7 @@ msgstr "Autor/Autora" #: bookwyrm/templates/import/import_status.html:112 msgid "Shelf" -msgstr "" +msgstr "Estantería" #: bookwyrm/templates/import/import_status.html:115 #: bookwyrm/templates/import/manual_review.html:13 @@ -1487,11 +1487,11 @@ msgstr "Estado" #: bookwyrm/templates/import/import_status.html:130 msgid "Import preview unavailable." -msgstr "" +msgstr "Previsualización de la importación no disponible." #: bookwyrm/templates/import/import_status.html:162 msgid "View imported review" -msgstr "" +msgstr "Ver reseña importada" #: bookwyrm/templates/import/import_status.html:176 msgid "Imported" @@ -1499,28 +1499,28 @@ msgstr "Importado" #: bookwyrm/templates/import/import_status.html:182 msgid "Needs manual review" -msgstr "" +msgstr "Necesita revisión manual" #: bookwyrm/templates/import/import_status.html:195 msgid "Retry" -msgstr "" +msgstr "Reintentar" #: bookwyrm/templates/import/import_status.html:213 msgid "This import is in an old format that is no longer supported. If you would like to troubleshoot missing items from this import, click the button below to update the import format." -msgstr "" +msgstr "Esta importación está en un formato antiguo que ya no es compatible. Si desea solucionar los elementos que faltan en esta importación, haga clic en el botón de abajo para actualizar el formato de importación." #: bookwyrm/templates/import/import_status.html:215 msgid "Update import" -msgstr "" +msgstr "Actualizar importación" #: bookwyrm/templates/import/manual_review.html:5 #: bookwyrm/templates/import/troubleshoot.html:4 msgid "Import Troubleshooting" -msgstr "" +msgstr "Solucionar Importación" #: bookwyrm/templates/import/manual_review.html:21 msgid "Approving a suggestion will permanently add the suggested book to your shelves and associate your reading dates, reviews, and ratings with that book." -msgstr "" +msgstr "La aprobación de una sugerencia añadirá permanentemente el libro sugerido a tus estanterías y asociará tus fechas de lectura, tus reseñas y tus valoraciones a ese libro." #: bookwyrm/templates/import/manual_review.html:58 #: bookwyrm/templates/lists/curate.html:57 @@ -1529,7 +1529,7 @@ msgstr "Aprobar" #: bookwyrm/templates/import/manual_review.html:66 msgid "Reject" -msgstr "" +msgstr "Rechazar" #: bookwyrm/templates/import/tooltip.html:6 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." @@ -1537,31 +1537,31 @@ msgstr "Puede descargar sus datos de Goodreads desde la open an issue if you are seeing unexpected failed items." -msgstr "" +msgstr "Póngase en contacto con su administrador o cree una propuesta si está viendo elementos fallidos inesperados." #: bookwyrm/templates/landing/about.html:7 bookwyrm/templates/layout.html:230 #, python-format diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index 34b8aeedab9737438319fddeb6fb023d01472536..4cdcbf8ea2a3ffdeed740317a055f435e5954b7c 100644 GIT binary patch delta 16292 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 bJG>HPr$T97D%^5~l+?+gf2L1f^j8P~Hun!& literal 65002 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 UY0tE$Yo~)Z0E1e@SdM@N08wWSegFUf diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index 25db17d99..fc1ecf41c 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-17 18:03+0000\n" -"PO-Revision-Date: 2021-11-17 18:41\n" +"PO-Revision-Date: 2021-11-22 19:37\n" "Last-Translator: Mouse Reeve \n" "Language-Team: French\n" "Language: fr\n" @@ -99,7 +99,7 @@ msgstr "Suppression du modérateur" #: bookwyrm/models/base_model.py:21 msgid "Domain block" -msgstr "Bloc de domaine" +msgstr "Blocage de domaine" #: bookwyrm/models/book.py:233 msgid "Audiobook" @@ -184,7 +184,7 @@ msgstr "Español" #: bookwyrm/settings.py:168 msgid "Galego (Galician)" -msgstr "" +msgstr "Galego (Galicien)" #: bookwyrm/settings.py:169 msgid "Français (French)" @@ -192,7 +192,7 @@ msgstr "Français" #: bookwyrm/settings.py:170 msgid "Lietuvių (Lithuanian)" -msgstr "" +msgstr "Lietuvių (Lituanien)" #: bookwyrm/settings.py:171 msgid "Português - Brasil (Brazilian Portuguese)" @@ -1487,7 +1487,7 @@ msgstr "Statut" #: bookwyrm/templates/import/import_status.html:130 msgid "Import preview unavailable." -msgstr "" +msgstr "Aperçu de l'importation indisponible." #: bookwyrm/templates/import/import_status.html:162 msgid "View imported review" @@ -1503,15 +1503,15 @@ msgstr "Nécessite une vérification manuelle" #: bookwyrm/templates/import/import_status.html:195 msgid "Retry" -msgstr "" +msgstr "Réessayer" #: bookwyrm/templates/import/import_status.html:213 msgid "This import is in an old format that is no longer supported. If you would like to troubleshoot missing items from this import, click the button below to update the import format." -msgstr "" +msgstr "Cette importation est dans un ancien format qui n'est plus pris en charge. Si vous souhaitez corriger les éléments manquants de cette importation, cliquez sur le bouton ci-dessous pour mettre à jour le format d'importation." #: bookwyrm/templates/import/import_status.html:215 msgid "Update import" -msgstr "" +msgstr "Mettre à jour l'importation" #: bookwyrm/templates/import/manual_review.html:5 #: bookwyrm/templates/import/troubleshoot.html:4 diff --git a/locale/gl_ES/LC_MESSAGES/django.mo b/locale/gl_ES/LC_MESSAGES/django.mo index ad56b337193c5e6c8d5aab3c5f952421a6aa57a8..c8999f80404d6cb44fd86e16108a3b2469f6f5fc 100644 GIT binary patch delta 22449 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 HF@_lcsVr>d diff --git a/locale/gl_ES/LC_MESSAGES/django.po b/locale/gl_ES/LC_MESSAGES/django.po index 1008b2d46..958563626 100644 --- a/locale/gl_ES/LC_MESSAGES/django.po +++ b/locale/gl_ES/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-17 18:03+0000\n" -"PO-Revision-Date: 2021-11-19 16:48\n" +"PO-Revision-Date: 2021-11-19 17:43\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Galician\n" "Language: gl\n" @@ -3114,140 +3114,140 @@ msgstr "Crear estante" #, python-format msgid "%(formatted_count)s book" msgid_plural "%(formatted_count)s books" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(formatted_count)s libro" +msgstr[1] "%(formatted_count)s libros" #: bookwyrm/templates/shelf/shelf.html:97 #, python-format msgid "(showing %(start)s-%(end)s)" -msgstr "" +msgstr "(mostrando %(start)s-%(end)s)" #: bookwyrm/templates/shelf/shelf.html:109 msgid "Edit shelf" -msgstr "" +msgstr "Editar estante" #: bookwyrm/templates/shelf/shelf.html:117 msgid "Delete shelf" -msgstr "" +msgstr "Eliminar estante" #: bookwyrm/templates/shelf/shelf.html:145 #: bookwyrm/templates/shelf/shelf.html:171 msgid "Shelved" -msgstr "" +msgstr "No estante" #: bookwyrm/templates/shelf/shelf.html:146 #: bookwyrm/templates/shelf/shelf.html:174 msgid "Started" -msgstr "" +msgstr "Comezado" #: bookwyrm/templates/shelf/shelf.html:147 #: bookwyrm/templates/shelf/shelf.html:177 msgid "Finished" -msgstr "" +msgstr "Rematado" #: bookwyrm/templates/shelf/shelf.html:203 msgid "This shelf is empty." -msgstr "" +msgstr "Este estante esta baleiro." #: bookwyrm/templates/snippets/add_to_group_button.html:15 msgid "Invite" -msgstr "" +msgstr "Convidar" #: bookwyrm/templates/snippets/add_to_group_button.html:24 msgid "Uninvite" -msgstr "" +msgstr "Retirar convite" #: bookwyrm/templates/snippets/add_to_group_button.html:28 #, python-format msgid "Remove @%(username)s" -msgstr "" +msgstr "Eliminar @%(username)s" #: bookwyrm/templates/snippets/announcement.html:31 #, python-format msgid "Posted by %(username)s" -msgstr "" +msgstr "Publicado por %(username)s" #: bookwyrm/templates/snippets/authors.html:22 #, python-format msgid "and %(remainder_count_display)s other" msgid_plural "and %(remainder_count_display)s others" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "e %(remainder_count_display)s outro" +msgstr[1] "e %(remainder_count_display)s outros" #: bookwyrm/templates/snippets/book_cover.html:61 msgid "No cover" -msgstr "" +msgstr "Sen portada" #: bookwyrm/templates/snippets/book_titleby.html:6 #, python-format msgid "%(title)s by" -msgstr "" +msgstr "%(title)s por" #: bookwyrm/templates/snippets/boost_button.html:20 #: bookwyrm/templates/snippets/boost_button.html:21 msgid "Boost" -msgstr "" +msgstr "Promover" #: bookwyrm/templates/snippets/boost_button.html:33 #: bookwyrm/templates/snippets/boost_button.html:34 msgid "Un-boost" -msgstr "" +msgstr "Retirar promoción" #: bookwyrm/templates/snippets/create_status.html:39 msgid "Quote" -msgstr "" +msgstr "Cita" #: bookwyrm/templates/snippets/create_status/comment.html:15 msgid "Some thoughts on the book" -msgstr "" +msgstr "Cousas interesantes no libro" #: bookwyrm/templates/snippets/create_status/comment.html:27 #: bookwyrm/templates/snippets/reading_modals/progress_update_modal.html:15 msgid "Progress:" -msgstr "" +msgstr "Progreso:" #: bookwyrm/templates/snippets/create_status/comment.html:53 #: bookwyrm/templates/snippets/progress_field.html:18 msgid "pages" -msgstr "" +msgstr "páxinas" #: bookwyrm/templates/snippets/create_status/comment.html:59 #: bookwyrm/templates/snippets/progress_field.html:23 msgid "percent" -msgstr "" +msgstr "porcentaxe" #: bookwyrm/templates/snippets/create_status/comment.html:66 #, python-format msgid "of %(pages)s pages" -msgstr "" +msgstr "de %(pages)s páxinas" #: bookwyrm/templates/snippets/create_status/content_field.html:17 #: bookwyrm/templates/snippets/status/layout.html:34 #: bookwyrm/templates/snippets/status/layout.html:52 #: bookwyrm/templates/snippets/status/layout.html:53 msgid "Reply" -msgstr "" +msgstr "Responder" #: bookwyrm/templates/snippets/create_status/content_field.html:17 msgid "Content" -msgstr "" +msgstr "Contido" #: bookwyrm/templates/snippets/create_status/content_warning_field.html:10 msgid "Content warning:" -msgstr "" +msgstr "Aviso sobre o contido:" #: bookwyrm/templates/snippets/create_status/content_warning_field.html:18 msgid "Spoilers ahead!" -msgstr "" +msgstr "Contén Spoilers!" #: bookwyrm/templates/snippets/create_status/content_warning_toggle.html:13 msgid "Include spoiler alert" -msgstr "" +msgstr "Incluír alerta de spoiler" #: bookwyrm/templates/snippets/create_status/layout.html:48 #: bookwyrm/templates/snippets/reading_modals/form.html:7 msgid "Comment:" -msgstr "" +msgstr "Comentario:" #: bookwyrm/templates/snippets/create_status/post_options_block.html:8 #: bookwyrm/templates/snippets/privacy-icons.html:15 @@ -3255,60 +3255,60 @@ msgstr "" #: bookwyrm/templates/snippets/privacy_select.html:20 #: bookwyrm/templates/snippets/privacy_select_no_followers.html:17 msgid "Private" -msgstr "" +msgstr "Privado" #: bookwyrm/templates/snippets/create_status/post_options_block.html:21 msgid "Post" -msgstr "" +msgstr "Publicación" #: bookwyrm/templates/snippets/create_status/quotation.html:17 msgid "Quote:" -msgstr "" +msgstr "Cita:" #: bookwyrm/templates/snippets/create_status/quotation.html:25 #, python-format msgid "An excerpt from '%(book_title)s'" -msgstr "" +msgstr "Un extracto de '%(book_title)s'" #: bookwyrm/templates/snippets/create_status/quotation.html:32 msgid "Position:" -msgstr "" +msgstr "Posición:" #: bookwyrm/templates/snippets/create_status/quotation.html:45 msgid "On page:" -msgstr "" +msgstr "Na páxina:" #: bookwyrm/templates/snippets/create_status/quotation.html:51 msgid "At percent:" -msgstr "" +msgstr "Na porcentaxe:" #: bookwyrm/templates/snippets/create_status/review.html:25 #, python-format msgid "Your review of '%(book_title)s'" -msgstr "" +msgstr "A túa recensión de '%(book_title)s'" #: bookwyrm/templates/snippets/create_status/review.html:40 msgid "Review:" -msgstr "" +msgstr "Recensión:" #: bookwyrm/templates/snippets/delete_readthrough_modal.html:4 msgid "Delete these read dates?" -msgstr "" +msgstr "Eliminar estas datas de lectura?" #: bookwyrm/templates/snippets/delete_readthrough_modal.html:7 #, python-format msgid "You are deleting this readthrough and its %(count)s associated progress updates." -msgstr "" +msgstr "Vas eliminar o diario de lectura e as súas %(count)s actualizacións de progreso da lectura." #: bookwyrm/templates/snippets/fav_button.html:16 #: bookwyrm/templates/snippets/fav_button.html:17 msgid "Like" -msgstr "" +msgstr "Gústame" #: bookwyrm/templates/snippets/fav_button.html:30 #: bookwyrm/templates/snippets/fav_button.html:31 msgid "Un-like" -msgstr "" +msgstr "Retirar gústame" #: bookwyrm/templates/snippets/filters_panel/filters_panel.html:7 msgid "Show filters" @@ -3391,26 +3391,26 @@ msgstr[1] "valorado %(title)s: %(display_ratin #, python-format msgid "Review of \"%(book_title)s\" (%(display_rating)s star): %(review_title)s" msgid_plural "Review of \"%(book_title)s\" (%(display_rating)s stars): %(review_title)s" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Recensión de \"%(book_title)s\" (%(display_rating)s estrela): %(review_title)s" +msgstr[1] "Recensión de \"%(book_title)s\" (%(display_rating)s estrelas): %(review_title)s" #: bookwyrm/templates/snippets/generated_status/review_pure_name.html:8 #, python-format msgid "Review of \"%(book_title)s\": %(review_title)s" -msgstr "" +msgstr "Recensión de \"%(book_title)s\": %(review_title)s" #: bookwyrm/templates/snippets/goal_form.html:4 #, python-format msgid "Set a goal for how many books you'll finish reading in %(year)s, and track your progress throughout the year." -msgstr "" +msgstr "Establece un obxectivo de cantos libros queres ler en %(year)s, e controla a túa progresión durante o ano." #: bookwyrm/templates/snippets/goal_form.html:16 msgid "Reading goal:" -msgstr "" +msgstr "Obxectivo de lectura:" #: bookwyrm/templates/snippets/goal_form.html:21 msgid "books" -msgstr "" +msgstr "libros" #: bookwyrm/templates/snippets/goal_form.html:26 msgid "Goal privacy:" @@ -3652,51 +3652,51 @@ msgstr "recensionou %(book)s" #: bookwyrm/templates/snippets/status/headers/to_read.html:7 #, python-format msgid "%(username)s wants to read %(book)s" -msgstr "" +msgstr "%(username)s quere ler %(book)s" #: bookwyrm/templates/snippets/status/layout.html:24 #: bookwyrm/templates/snippets/status/status_options.html:17 msgid "Delete status" -msgstr "" +msgstr "Eliminar estado" #: bookwyrm/templates/snippets/status/layout.html:56 #: bookwyrm/templates/snippets/status/layout.html:57 msgid "Boost status" -msgstr "" +msgstr "Promover estado" #: bookwyrm/templates/snippets/status/layout.html:60 #: bookwyrm/templates/snippets/status/layout.html:61 msgid "Like status" -msgstr "" +msgstr "Gustar estado" #: bookwyrm/templates/snippets/status/status.html:10 msgid "boosted" -msgstr "" +msgstr "promovido" #: bookwyrm/templates/snippets/status/status_options.html:7 #: bookwyrm/templates/snippets/user_options.html:7 msgid "More options" -msgstr "" +msgstr "Máis opcións" #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" -msgstr "" +msgstr "Cambiar a esta edición" #: bookwyrm/templates/snippets/table-sort-header.html:6 msgid "Sorted ascending" -msgstr "" +msgstr "Orde ascendente" #: bookwyrm/templates/snippets/table-sort-header.html:10 msgid "Sorted descending" -msgstr "" +msgstr "Orde descendente" #: bookwyrm/templates/snippets/trimmed_text.html:17 msgid "Show more" -msgstr "" +msgstr "Mostrar máis" #: bookwyrm/templates/snippets/trimmed_text.html:35 msgid "Show less" -msgstr "" +msgstr "Mostrar menos" #: bookwyrm/templates/user/books_header.html:10 msgid "Your books" @@ -3705,166 +3705,166 @@ msgstr "Os teus libros" #: bookwyrm/templates/user/books_header.html:15 #, python-format msgid "%(username)s's books" -msgstr "" +msgstr "Libros de %(username)s" #: bookwyrm/templates/user/goal.html:8 #, python-format msgid "%(year)s Reading Progress" -msgstr "" +msgstr "Progresión da lectura en %(year)s" #: bookwyrm/templates/user/goal.html:12 msgid "Edit Goal" -msgstr "" +msgstr "Editar obxectivo" #: bookwyrm/templates/user/goal.html:28 #, python-format msgid "%(name)s hasn't set a reading goal for %(year)s." -msgstr "" +msgstr "%(name)s non estableceu un obxectivo de lectura para %(year)s." #: bookwyrm/templates/user/goal.html:40 #, python-format msgid "Your %(year)s Books" -msgstr "" +msgstr "O teus libros de %(year)s" #: bookwyrm/templates/user/goal.html:42 #, python-format msgid "%(username)s's %(year)s Books" -msgstr "" +msgstr "Libros de %(username)s para %(year)s" #: bookwyrm/templates/user/groups.html:9 msgid "Your Groups" -msgstr "" +msgstr "Os teus grupos" #: bookwyrm/templates/user/groups.html:11 #, python-format msgid "Groups: %(username)s" -msgstr "" +msgstr "Grupos: %(username)s" #: bookwyrm/templates/user/groups.html:17 msgid "Create group" -msgstr "" +msgstr "Crear grupo" #: bookwyrm/templates/user/layout.html:19 bookwyrm/templates/user/user.html:10 msgid "User Profile" -msgstr "" +msgstr "Perfil da usuaria" #: bookwyrm/templates/user/layout.html:45 msgid "Follow Requests" -msgstr "" +msgstr "Solicitudes de seguimento" #: bookwyrm/templates/user/layout.html:70 msgid "Reading Goal" -msgstr "" +msgstr "Obxectivo de lectura" #: bookwyrm/templates/user/layout.html:76 msgid "Groups" -msgstr "" +msgstr "Grupos" #: bookwyrm/templates/user/lists.html:11 #, python-format msgid "Lists: %(username)s" -msgstr "" +msgstr "Listas: %(username)s" #: bookwyrm/templates/user/lists.html:17 bookwyrm/templates/user/lists.html:29 msgid "Create list" -msgstr "" +msgstr "Crear lista" #: bookwyrm/templates/user/relationships/followers.html:12 #, python-format msgid "%(username)s has no followers" -msgstr "" +msgstr "%(username)s non ten seguidoras" #: bookwyrm/templates/user/relationships/following.html:6 #: bookwyrm/templates/user/relationships/layout.html:15 msgid "Following" -msgstr "" +msgstr "Seguindo" #: bookwyrm/templates/user/relationships/following.html:12 #, python-format msgid "%(username)s isn't following any users" -msgstr "" +msgstr "%(username)s non segue a ninguén" #: bookwyrm/templates/user/user.html:16 msgid "Edit profile" -msgstr "" +msgstr "Editar perfil" #: bookwyrm/templates/user/user.html:33 #, python-format msgid "View all %(size)s" -msgstr "" +msgstr "Ver tódolos %(size)s" #: bookwyrm/templates/user/user.html:46 msgid "View all books" -msgstr "" +msgstr "Ver tódolos libros" #: bookwyrm/templates/user/user.html:59 msgid "User Activity" -msgstr "" +msgstr "Actividade da usuaria" #: bookwyrm/templates/user/user.html:63 msgid "RSS feed" -msgstr "" +msgstr "Fonte RSS" #: bookwyrm/templates/user/user.html:74 msgid "No activities yet!" -msgstr "" +msgstr "Sen actividade!" #: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" -msgstr "" +msgstr "Uniuse en %(date)s" #: bookwyrm/templates/user/user_preview.html:26 #, python-format msgid "%(counter)s follower" msgid_plural "%(counter)s followers" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(counter)s seguidora" +msgstr[1] "%(counter)s seguidoras" #: bookwyrm/templates/user/user_preview.html:27 #, python-format msgid "%(counter)s following" -msgstr "" +msgstr "Seguindo a %(counter)s" #: bookwyrm/templates/user/user_preview.html:34 #, python-format msgid "%(mutuals_display)s follower you follow" msgid_plural "%(mutuals_display)s followers you follow" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(mutuals_display)s seguidora que segues" +msgstr[1] "%(mutuals_display)s seguidoras que segues" #: bookwyrm/templates/user/user_preview.html:38 msgid "No followers you follow" -msgstr "" +msgstr "Sen seguidoras que ti segues" #: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" -msgstr "" +msgstr "O ficheiro supera o tamaño máximo: 10MB" #: bookwyrm/templatetags/utilities.py:31 #, python-format msgid "%(title)s: %(subtitle)s" -msgstr "" +msgstr "%(title)s: %(subtitle)s" #: bookwyrm/views/imports/import_data.py:64 msgid "Not a valid csv file" -msgstr "" +msgstr "Non é un ficheiro csv válido" #: bookwyrm/views/landing/login.py:69 msgid "Username or password are incorrect" -msgstr "" +msgstr "O nome de usuaria ou contrasinal non son correctos" #: bookwyrm/views/landing/password.py:32 msgid "No user with that email address was found." -msgstr "" +msgstr "Non atopamos unha usuaria con ese email." #: bookwyrm/views/landing/password.py:43 #, python-brace-format msgid "A password reset link was sent to {email}" -msgstr "" +msgstr "Enviamos unha ligazón de restablecemento a {email}" #: bookwyrm/views/rss_feed.py:35 #, python-brace-format msgid "Status updates from {obj.display_name}" -msgstr "" +msgstr "Actualizacións de estados desde {obj.display_name}" diff --git a/locale/lt_LT/LC_MESSAGES/django.mo b/locale/lt_LT/LC_MESSAGES/django.mo index 6a72ab36cef1f22fa4663fd9dadbbda3c88c5083..728d0e905df147942efe7c21b5ba4bc4af36dd39 100644 GIT binary patch delta 20727 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 diff --git a/locale/lt_LT/LC_MESSAGES/django.po b/locale/lt_LT/LC_MESSAGES/django.po index 9928785a6..16110b069 100644 --- a/locale/lt_LT/LC_MESSAGES/django.po +++ b/locale/lt_LT/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-17 18:03+0000\n" -"PO-Revision-Date: 2021-11-17 20:02\n" +"PO-Revision-Date: 2021-11-22 08:50\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Lithuanian\n" "Language: lt\n" @@ -48,7 +48,7 @@ msgstr "Neribota" #: bookwyrm/forms.py:338 msgid "List Order" -msgstr "Sąrašo užsakymas" +msgstr "Kaip pridėta į sąrašą" #: bookwyrm/forms.py:339 msgid "Book Title" @@ -184,7 +184,7 @@ msgstr "Español (Ispanų)" #: bookwyrm/settings.py:168 msgid "Galego (Galician)" -msgstr "" +msgstr "Galego (galisų)" #: bookwyrm/settings.py:169 msgid "Français (French)" @@ -192,7 +192,7 @@ msgstr "Français (Prancūzų)" #: bookwyrm/settings.py:170 msgid "Lietuvių (Lithuanian)" -msgstr "" +msgstr "Lietuvių" #: bookwyrm/settings.py:171 msgid "Português - Brasil (Brazilian Portuguese)" @@ -1410,11 +1410,11 @@ msgstr "Importavimo būsena" #: bookwyrm/templates/import/import_status.html:13 #: bookwyrm/templates/import/import_status.html:27 msgid "Retry Status" -msgstr "" +msgstr "Pakartojimo būsena" #: bookwyrm/templates/import/import_status.html:22 msgid "Imports" -msgstr "" +msgstr "Importai" #: bookwyrm/templates/import/import_status.html:39 msgid "Import started:" @@ -1422,38 +1422,38 @@ msgstr "Importavimas prasidėjo:" #: bookwyrm/templates/import/import_status.html:48 msgid "In progress" -msgstr "" +msgstr "Vykdoma" #: bookwyrm/templates/import/import_status.html:50 msgid "Refresh" -msgstr "" +msgstr "Atnaujinti" #: bookwyrm/templates/import/import_status.html:71 #, python-format msgid "%(display_counter)s item needs manual approval." msgid_plural "%(display_counter)s items need manual approval." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "%(display_counter)s reikia manualaus patvirtinimo." +msgstr[1] "%(display_counter)s reikia manualaus patvirtinimo." +msgstr[2] "%(display_counter)s reikia manualaus patvirtinimo." +msgstr[3] "%(display_counter)s reikia manualaus patvirtinimo." #: bookwyrm/templates/import/import_status.html:76 #: bookwyrm/templates/import/manual_review.html:8 msgid "Review items" -msgstr "" +msgstr "Peržiūrėti elementus" #: bookwyrm/templates/import/import_status.html:82 #, python-format msgid "%(display_counter)s item failed to import." msgid_plural "%(display_counter)s items failed to import." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "%(display_counter)s nepavyko importuoti." +msgstr[1] "%(display_counter)s nepavyko importuoti." +msgstr[2] "%(display_counter)s nepavyko importuoti." +msgstr[3] "%(display_counter)s nepavyko importuoti." #: bookwyrm/templates/import/import_status.html:88 msgid "View and troubleshoot failed items" -msgstr "" +msgstr "Žiūrėkite ir taisykite nepavykusius elementus" #: bookwyrm/templates/import/import_status.html:100 msgid "Row" @@ -1477,7 +1477,7 @@ msgstr "Autorius" #: bookwyrm/templates/import/import_status.html:112 msgid "Shelf" -msgstr "" +msgstr "Lentyna" #: bookwyrm/templates/import/import_status.html:115 #: bookwyrm/templates/import/manual_review.html:13 @@ -1501,11 +1501,11 @@ msgstr "Būsena" #: bookwyrm/templates/import/import_status.html:130 msgid "Import preview unavailable." -msgstr "" +msgstr "Nepavyko įkelti peržiūros." #: bookwyrm/templates/import/import_status.html:162 msgid "View imported review" -msgstr "" +msgstr "Peržiūrėti įkeltą atsiliepimą" #: bookwyrm/templates/import/import_status.html:176 msgid "Imported" @@ -1513,28 +1513,28 @@ msgstr "Importuota" #: bookwyrm/templates/import/import_status.html:182 msgid "Needs manual review" -msgstr "" +msgstr "Reikalingas manualus atsiliepimas" #: bookwyrm/templates/import/import_status.html:195 msgid "Retry" -msgstr "" +msgstr "Bandyti dar kartą" #: bookwyrm/templates/import/import_status.html:213 msgid "This import is in an old format that is no longer supported. If you would like to troubleshoot missing items from this import, click the button below to update the import format." -msgstr "" +msgstr "Tai seno formato importas, kuris nebepalaikomas. Jei norite matyti importo metu praleistus elementus, spustelėkite žemiau esantį mygtuką ir atnaujinkite importavimo formatą." #: bookwyrm/templates/import/import_status.html:215 msgid "Update import" -msgstr "" +msgstr "Atnaujinti importą" #: bookwyrm/templates/import/manual_review.html:5 #: bookwyrm/templates/import/troubleshoot.html:4 msgid "Import Troubleshooting" -msgstr "" +msgstr "Importo problemų sprendimas" #: bookwyrm/templates/import/manual_review.html:21 msgid "Approving a suggestion will permanently add the suggested book to your shelves and associate your reading dates, reviews, and ratings with that book." -msgstr "" +msgstr "Jei patvirtinsite siūlymą, siūloma knyga visam laikui bus įkelta į Jūsų lentyną, susieta su skaitymo datomis, atsiliepimais ir knygos reitingais." #: bookwyrm/templates/import/manual_review.html:58 #: bookwyrm/templates/lists/curate.html:57 @@ -1551,31 +1551,31 @@ msgstr "Galite atsisiųsti savo „Goodreads“ duomenis iš open an issue if you are seeing unexpected failed items." -msgstr "" +msgstr "Jei matote netikėtų nesklandumų, susisiekite su administratoriumi arba registruokite problemą." #: bookwyrm/templates/landing/about.html:7 bookwyrm/templates/layout.html:230 #, python-format @@ -3666,7 +3666,7 @@ msgstr "pacitavo %(book)s" #: bookwyrm/templates/snippets/status/headers/rating.html:3 #, python-format msgid "rated %(book)s:" -msgstr "įvertinta %(book)s:" +msgstr "įvertino %(book)s:" #: bookwyrm/templates/snippets/status/headers/read.html:7 #, python-format @@ -3846,7 +3846,7 @@ msgstr "Įrašų dar nėra" #: bookwyrm/templates/user/user_preview.html:22 #, python-format msgid "Joined %(date)s" -msgstr "Joined %(date)s" +msgstr "Prisijungė %(date)s" #: bookwyrm/templates/user/user_preview.html:26 #, python-format diff --git a/locale/zh_Hans/LC_MESSAGES/django.mo b/locale/zh_Hans/LC_MESSAGES/django.mo index da41e106d8f6fb8769409570da5a1bc960a3ddee..1d1227f8092b70c68bb692fb532759090142aa83 100644 GIT binary patch delta 16563 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 delta 27210 zcmX?bgXzgO=K6a=EK?a67#L)k85m?37#LV285q=A7#Q9dfU+uwm2~`I599VoN{7duwh_e;B{tT&|_d=@N#BgkY-?DsB~svFk)a}nCcACcfy&0 zL5zWc;j=RXg98Ht1D6W}LjVH6WJ;NLq1_pTs28OdP3=I4X3=D5w7#PGE z7#RM#Ffb@EFffR^GBEfsFff?8GBAiRFfcT`LgZ(-GBC(8FfeRzWnc(lU|=}s%D|w; zz`&sF1`+pigQ(ANV_;BXU|^_qV_;BZU|?9_2Jy%tHwFethI$5u8*UJbKe;h5m@qIf zFu5}@a4|42n7c#7o!l81R2di;g4`Jx_!t-%D%>GHZFgs2P-b9YSnLk*@o{$shI|GF zhF?%R%Y%U-kAZ>VmInhvFaraFrzZnL0s{lXTu%muC%7zDf-7!ny67;?NB7z9B+^JZYEVqjo+;LX4g$-ux6?E?wQtv-;T{pQ2K zUVj8&ttRD4*32qJh^B;vf+}h&nYt1_qFRJwFBpW>ARvF);8j zFfdp{#XbBO7&sXi7y|tuAsOul3Bhcrc$FVRJy=1DA0){8pa#tJV_*BGYz78~!~jU*I~xEo?>$t#QhgxAc5J(8!3xTACXCa`Fu4iC)50&@{bqHf9#9(14tr!Y%pnfO=gA@Y;gJUQp z3SyviekjD?rcj8(xUEcau_6k7lbh|STQg#w1h#5=KW!iMEEWY;*h9t zh=Z%b85rt81x!;oC@2^hri4S{ZeBRV;+0VTws1&@9E9@EheI56D;$!@UWP-8+IQg) zhcib&)bmF`qE0pf;$!0oh(42? zAR)J;J_-^aS(Il;vgZU7Y7L;vp9%D zJmaAGKPV0ocWH5uL{=CFadADA-xmi7nK@7c7R5m<+!_a|Ob*6DJn$tB;(_0B5QhrH zLs~*o@sJR+h=+*V#zR8PJ)VJ~9#pM{Koum!LmZGA4>71X9%4~PJjBIQp!D2$h=Z2J zGcb5CFfgo%hdAJCJS6DNJ)gmU1cJqx@}BkU{D9O`JnQr6CpwS0BXV0M2N#bL(TaEwTLGP z62)Rk5RWP*K|G*ap9HbcK8bls>8ARUi| zDUhJsmjWq}jzjsNf*sVz8hy%Ky^z>9n+%HLm zgvh#7PzcpCFlFnTIN)MB#GnsQb-&UfLCl{4@u7GIBno9SKt5$)P|1LVh*1W_ z!S)#p4E3P)zDEYcpa7^uR0ab>76SuAat0*s&Or_Qn*j+a=1fR+%#jI6yo#BS{B4*C zaez}M1A{TBPnZemsMKXbEZm<7anOlOh<)cXq3!>hP>qi>AufHL38|faWX*iWkC!~%L4V~7#MQ1AP#HKf`r(DEQm#?vmg$?ngt1gTTuFWRz0K${gMR< zYV~Z04{Wj_E_Q*^zEJV7Y)Bf2%ZB(oHyhG7tcA)ihSIB{`Zi}n9K0tR;*fLM5C`AL zhD7!K`fNxdd7aI`paSX?W<%mwIR|2aeGVkm`{zL7G%5#TKtc}0f$2FApA|sGOLHI| zsL6piv;`_ZIS1nN899&;UJB*cZ-y#70JZQuRN{UPBuL*tHL&GEG>YUx9H5j7aiAuY zZwci)ohyaA;jA$tMD9N_{;$Ve4H zJfu|s$<8)Very3GD)I{$7(_t%zXoc+!~#gRnG02Lu>j(Odj*i7e_H^t_%~ENe<8#{ z(uI&js89$|?^XzLcxWNSqS!)6XEdvjfgzWHfg!ID_0cFJyhcy&Kf_7ptB&Zh`LyG9l z#gN+bR52viyeft`@M|%|A&eyu^Y}|3`ov4>A#tV-70@ez6gYMzkVF**)lgdkad|6L zT_2P`uLPohc?raU>!9L0N+2P0umln^k4qql_$Smnky40*Wa>*H8nsFxE;1>F1i4Eo z#KOQ*NH;nPs$okhBq$F-)mU{ z19%&f9jLr~1tf?~Dj>PQz5)^w zt`(3V_JN9rR6wF2ssfT&(<&ey%ZAYP3?&ti5U7P}Y=_eQ6_5~_UI9t<%OM&Vc2_`r zd<4qB4b}ey%6|vd_Z`Y-uY@>Apb`?~5|s=LM;RCx)G9$9sAph!QwbS%`wmqQTm^}O zL@1qC1qqSrDu_cTR6%?&s|u1x7emF5RY5}HLKP$=u2n%2^Ebi41m&QUBW>-U^qP801kO|e05LsFc3EG`dbw{BVT(5@2?SpDa zBK}tm@sMf_#DPXNkPxw`VPL2SWj}`+h{aJg3=I7Y3=9P|5C<^SLVV0u3yBJeT8IG} zwGer|TF6+gO)X>qvbPqJ_zu@HFl=C8V0c#x8M>Wc$G{NBz`*dP4$^S(hSs`S^$hh4 zL7*YgdPu(gP|pA!=@e*ylmp!j;6Y-B?F|qIzG#3r^@=crS85oKf7#JLyAZcJTRD!=5;zOxsNOsd`hG;Zz zhB(Bz8RFo`W{3rq&5%Lpwq{7&-)@GO`=}Wb0--ICkXh6M3Bj{1kSMrZ-@?G)%fP^J zy9Ltz*KCFGD_S89lVhz63``6R3_n{T1CoDQA!$Lc4PuaE8ze;B+aQT6ybTf+32hLE zO>1Ld&;T{x+aTtjX@i86bUOosGXn!deOf!j!c|a#AMFebjtmS8HXRTH>pB=1ycrl6 z+B+a2aJd8Gqx(==rxPMy*$IiNqn(iQ4rF9S2rZ64nxIHcSF*~MJWBZn}J~x0|SF*4@CW*9?0~Sf#Fdfq``4}0>t1i6CmpNCPJEW1`{DoxzLFa`ND~iY}q{#l1Nuhgx3FiCqfE} zOA{e2p#M& zozB3J4$2i!zVi%7oGzRJiMu~DAP$Y4$-q#-z`#&ElYzk%RKUz+V6bOkU@)2m3Av(K zkj`lLEJ#UscorlZzM2Jbpy=#+NMf^{4GBW$*^tB%F&k3y#m|NWeI``A97@+g=~gJ+ zGaHiKCeH>XDh7rHQ1KN|dOg&fZBTVbp!CIhDC6F2NXzCml>Y}xbIySnEC!{O=Rktm z07^U0f#m(eCZsBhc?fFcxcxgh&@N3;`LYOKwNwWD)0nq(Q7FE z18NcLT!=#?=0fth>Rbi}GX@5Ru(=Qi^+M$r%!MSfwR0gBUxd;(=0Y5BAIg6@mw^E^ z{><=UE+n6N%!Bx#Y#zi%tL8xr*fkH*EI$b42h4}~Fnm75K}qu=>hkA9d{#Cek`3GE zL(;%XsQjV%5RaaO@-NN@IUF?q2Q}z5RKpJ_UvL4$0=WecjoJ$!L2A4JVxi*#h>tuL zKpY&j0OEk81&~}*3{}?-mG6V{=PiIF=A|HUQ2o!a5K{06EQA=`w-93B)P;~#z7#6H zdm+R@hZaH{bbcYkhu5Ltcp_ z@T4;DVu%Zsp|sXwh|3M3v>lZ8hSCvGI(0F`VMS1WE0mrDrRPKGHH#r3wR16~Jh-$N z(hBBUQqRDU$-uy1xdc)IE?xq0$T28=b_pcNt}KE0^d6Lc1Eqg0fjE?7DMVg$DTJ@Q z6w>7~fQp+yX(yv9J&-Q30h}q4XpuJs(Q1fzmsdLVR>=DWnL#zZ4P@ z|Dd$sGDsAtEQ3_PR?8sv^e=-%@iZvEe%>;OOO`?P^$S(if$ z5|!K9^e#2?=c|-x8|M4a)b0@}nU9dWOX15Etbwhq$;5s-R~%q{}oJqL5)7 zl->=s-~^O^4N5%)SSX#f0#ePEuV7%X zWnf^KyaM9Wi(m~53^!IleE1rw{^tsa2iR6ZEaF=Uk(XWx30cjR5RchH>EM+Rk7a_? zf%1RLN{9uMRzeJ#xf0^Sg)1RJyJaOLG3{RoseTVb)t`Y{co|ARfQr9e2`K@;K*hyY zLCjZP1+iFb6{LuEUB$pq51OyfTm^A?*(ylE)4U4egUL{h3s*sE#}!a@dsjhxb_z=0 zTLsA_pP=%8pfu-dh)2X$L(JEN^37I5%=cW)P!C>k5WX4`MDeR3E-i&BtbuCmhiaI! z8q)Gv1r^^3KcgoR%;;H-Ej@H|DUo3;==4TkPxVV z@;jg!rb5N%tbsUm%^FD599jd3lCx0y+8RiE;{F;)Z}}-yzs6cfcGX`CaexPu_OD+H z38JvI5C>#J=`yHzGn7AVEhNYmuZ0BlMyLV1q4I~I>d!;@kD&B>DE$XYbFPD!Beo7= zU%d*HVYm*G`0Svx+d4>4`>lhxI2NidWgR5$3!&nz>mW_4o^_BQ-wxIH6e|B^9VA45 zL-lj7hv=7B54NwKK?lNMFj)_AkquOV=XywW8oM6S$IDv}X+H0Vs=EuNU#*99r@ya< zIFxe(#2kSQ5WXywud)H+b3-U?50?Ag$WW4Uqib09L@jFb8VD;tdd= zY=DX%*Z|39$D#a}Q2GPZg6|u^K4f6s2+_y85mKJWZiF~6dLsja9w`53Y=p$=^o@|T zuy7;9AzPsIX{h+4jgTc*UpGR0X0!>S&vFxl@4N|Okr$MXg3?)=Aaz6)l%BZ>;(#5S zp!xqORN&Gkh>P!Uf~4-}P=h~hg0%mCZh|;aY%_$`+zheM2Fmx@49QmUn<3rrrp*wG z)^CP5V9#bq$liwP`@Wf>9=x1}eG6o4S85AHgUc3(1%XgH1u9;?1!8c^7D#s5xCPRV zKeYuC6`!_193Zk45;EpnAtjz8lpnJd5>jbfAs)@$3eEqePz5zmi8iRhKB)LqD1ZJ| z28IaG!lbQ`#_E5lyzw@O!M58VK6Kdz37Ld#kVISnm2cbzNdq0*Al>j|_1hpm7TgYT zk=%BOL26LG?skYzOt(Wq#2!iqLFv@(5Q{3dL(J)b(o>=4EZPn!uvTt|gv9>skS^LS zsQLBGJ0KQv?|>K}v;(3+eh0*draK@$$b_n^+5vHBBb46>r6)l3Pu~H_W=nQJLShqC z{v1^PDwO{SqOP9dCDg$0P>KIgnr$bfpy1sJ=}s%|gbYx+?Sxnmw-b^`b9O>JP`(r5 zusSH+1{Lpv(o=UrJUC}3BqUdY#p@Xu_CO^LLk+$F<=@*03EJ0C{%^1b1_q8@5Qp*a zf>^8!rL~~6;Vy_i3nR!Orc1 zxcDzroxpC0PsMjbn%(ldA#rNC8{)&H-Hd zg7_X(Bl8}J0la%4J`~>r8RL=L0~v70+5>UGEU5ecFo}K8{I9W(0Xz_?zYpSorhO2f_e1&9_CX9-ybogWMyLTt zpz>Fs^uv9SsCWnEi|>boh{}G*5RAosh`Dk5A@-!!?}xag2rALEAL7E!{g4otxF6z! zQDiK>h&4ARQ=e38mc*K+Fw30Lk~s2Ow#y4l2Ls0K`M}>!AXBq4X)J#_I zLy&=sd50h&dj1e-@k%`d!}mjwwwl9XNFr-K49PAV4?_l(P9271BY`6jas4BZlFb9k zPdNe^bgDf9@yOmIkdU~11Y+^yBao1K1?7K&(m#(dFz|r#KWI7vw0xHLD8%K0P+AU3 zYeQ)ZDD8R_;puapc*P0G81se`koLyK6QKED1_p-TCm>xcj*}3V@|=V;Hib_@EHFID zz|h6Oz~Fuo5(1Y_LLBn+BqV=-g6d;C1&Mp!Q;^Ya*;5P*mJAFGg{L3`535fxFwA3M zV0e5A(vE1VKMh$le)}|}2=+b$NrVMwAPt0hXCOX!c?P16=`5tVT?D1)o`uMtI191( z;aNyN|9BRnU-TSgVk6-kBxLrSgXDtC=O7-aXE_gH2tsK&D6M^-fguAlDRrKKA(VlE zVIfrfJCtU*07)}~7a;oOFF-;@=K{n5_E7QU3k(clpgE-rkdQro0W#Qi?gBUp>KS}4 zLNu0Lged5|2uVZ}E<#2wWx(0D@%{9o($fj$Mxc?5KLHR%6Iz(XQbx2}ix&cYuHa8$m zufQANpkhe60kOCTN>9E4@#!omf5{C3v# zGBPl5F)}dhV_;x-#>BuN&&0s6gOPz@Ark|`awY}_S0)CAlZ*@u+ZY)bPBAbr*fB9M z)H5iGe|k ziGkq&69dC~2FOg;83qQ1UM25L2v?o12}wu}r6_Dqmsa}N^( zgWP0AL-BeaMo24Q0uuwnB?bnDbxaHl|3FEN8KjqiVJp-L`Am?R9~~wJh7?8yhR0AF zxaBCHL_6l6h;Py?Mw^|L5vIxuNXn40Ruw=BLjmT z69a=F69a<;69a<@)Diob7#Nl^GBCu0QYten))*KV_A@asyn!m>VrF3IXJlYl0E&62 zm^u>!LpR7)DEEWoBS_!wA`g^^lQ)K^SUD8EBCg0|Ub)s3SpUn=>*n zFoRsrz`*d4fq`KwNRR=2foq>U&kFlPC;Sd7@!*!_O5(Y@?;1>e}!%nD1 z&>puQP)*MODN98dA=6k#pzu_dxUuMh1rSpwa|M?kW=lLo!H`fq~&E0|P@G69dCE zMh1p!P%+SUIMCKL(8j+yMh1oqCI*JDObqo5M?nff`<|E>7)lrz7^Xs9c#H`$AUhMZ z1euY6;V0A}5G4dvlg7xva0Tj!*Nl*5N#e|q$~%COfnhHL1H&9p!enA#m;y>qj0_CQ zObiSHj0_BO85kInV6{dY0|P@T$YjtiKPCo-=S&O?i$SggtsZ1zV3-8jO~}l^Ulhgr?$t9f zFf=eRFsx)`V3-fe9#EfwmMucnf+;qr#T=ko0#qh|LI-N`Bd`hx0or+13EJcd;eyxX zL7Cu+AH)Xj$pq2D%nS_mHJ~a96da5U47p4U3=XOIpkz7O4H z+6{FSXyyU5Z4oNXu$Pg6;U#Dx2dEMUEzn|MU}%6!o@9b-VcNjNz~Bk0riGXp7?wdT z>1JYJ&KUAv z7#L1N6@j)~K7i>26)B)%iiv??Iw`W*kUl1;dJx-$k%3_~BLhPYX!9Zy1H%)joFFp;LnA2PffRwptU#+bp>m*o#DX9; z$bJDP28J)7RuvNi!#hR>1`9?81`SYA0@Zkfk%8eq0|P@D)N#uh85qtmGB7YPF)-X< zf~-FWDRlyEda-5NY;T5RjWn^GTW@2E70XKT8L8*#?fkBax zfuRUg5P>Q#kn@-r7+!(4(SrQWz`(%H#K5qNiGiUM)K&mB9vK)Ic0uJprh|5{@-s6q zTw`QlkOvir3=9l^Ks%nHE?UIIz_1ClFBs$lsJ$S^T5TtPBi6{^+-R97)EFjz1#Ff=kUFr0;oUtnNh z&;hlrK?Z}@!!bbm(OgWB&f_dbNYCXeBLl-GsKL(}85mxGN>L^ThRI9}3_c*knHd;1 zfr@qp1_nPS28JG}T1h4bhK)>+rM4hD3PGbFphN+c2Z@1FHHcqpg<$I$7!7^qPU(g5lrF)=X6FfuS~0A&eA28MGC3=D^$dZ0=ePBAht6o48% zpgop{nHU(F85kH|gM7}&z>olhdqmV*SL zxEQK#3#hFMYGX1nFnj>DQ zJ0utx7;b|4Vo-;%GBPj-LD|KiZUCshVPs&aV`5-f0MY;|J{cGolo%NpDxvDMEEpIV zQb0>186jJlwV@K{p_VFw`cq5{49rZE6%EDeLCZP=p-Kcm%?41Dgo%N{n-Mau0J4S` zR8%l9Fla!HFkoU}Xk&s51)T(?aj5tX(6)c5S!ST72r~mi6exXz#Gz_H=7F#ZBLl-H zP#b9>R6{Eh1H*nO8>9fV;01Kj0*HMa)C~tEd^AHofMNjD4hF>-RIeW+1H)$~28NkX zzBnUfkZdDpuQ8~?V`5;4U}9kS!w6cx2&y?47#Lz085lZ1E&{a_KsG{g71Tn|*%6jZ z3=B&^Z6gK-hA#{Z3`>|GgIpa<3=CbMb~C6hVPs%f1GV@vBLhP!69dB$P`U)ID`c8{ z&&;hpC9}97C$TazNJsA^!B068!tF()m) zD6u3nFI}@(p|~UwWC5n&WOws>vU!QQshY(KMXBkT#U&s;`FRSN#R|ze`NgRzla(xH z3KeITq{c&)6{jW^C1-5jVG+m3Q;=GeoC*prl)EaPmZ(F(AEgcOf83oR*$PYZOHxxNAIOnM7G^C< z#3DMmus|J2Rnp`Jn@|O)VZ}E3iFOP&skwH3`3iaYC8@Xsl~+%jwvY$pg4iBlJm<_i@;(j`MHUi zd0=K{UU5lcUUDj!lb2eqkeiyDlv-4*IJwh4gB5JdU%9XJ>>6iSK` z)6z1N71E0Gb0M}P>{KYv%*jzmPc2bMR4_3xQ7B3+F38U-PE{z+NX=6yDXIhoX-U39 zVsdh7aj`;TUZp}oVo`}gewso_Myf($K|xMtav~_2^d>7h=GGUbDpcl|DioJO8Rdz2 zB?=|^3Mr{MsU@ijHpL}H`FZJfsv4kV2}uh!`cOgjVvseU>}0PH0t%$WWRSrM$%%P+ z`6UWTsS2feDfxM+dI}-=3I#>^$*HL+Itm3jsfop@3aNP|sYMD-mHDMb3I&P9#pU@$ zDIklJ^YhX&i*g|j$jr~vV{j}^PR&cn%u8o*EKz`_Ju3#s(v-}6P~cCV=2$XW%BhnL zoUyGoPj~vqIC+W7MEAUs)Vvaf^2DM%kY49}6uuP$Q~<;%%}D_z0EM*7ycC5*h1|rF z}tTK0AW_SO0lMc1$$iQPX6U8$N~zW$rEfO^%C<^ z6mk>u64O&t6p|_xY!VeRic-^Tl~gsr8VV9iGBk^o?4aDql5Xzo#TiNYiA5=sW8Hiu z5-W=tTv9!#%YqH!)9hGP6eo7dWvdCgr4BO)mFP5Q3DA3I#=}X{kl2 zdC958lc##fo4G&|GK5k{%E?d8W`J<47+mu6)JqgVxmcmNG(A1FxFj`20Tc+ulQ(-L zKtqhzQv(`I`kuP%pc1L1w0Ls3XCkK)$S|-IH+m|u<|bz5SWUj@De9h=o|9Re!Qfg{ zlwYKflb;BRcyK&Gg$nYELB$)?CM63S&dFG$`GJiUv?B2Bm?b)ZF~CRHR%C@-0Mr zF_f}WKx8Z)&0+?R#G({%%uHtVQD9EZDVQwpBWahJk_z*#M}BT91Bg%v$;?g7$;?Y- z@C;CJgp@}L@GwOZw3_Vcvt=@`uMP*em`zQwnw;zF#Nn7+l3A8nQaO34Z=q93YEfBY zjunGv9w_J%GmBCcJYB%t%#u`)D5#e~nFg~>6R47TUD6yJsQhsR(s0u(-HC7<`vQ&jc1yH4w zmk#BE6Zqr{{_2|z0vs5b64NI?jL>5D1?RJ($vJ_B{CTB`IXRV}BCaUEEH!0vf1o%k zxU8K#KSZiNKTjc10c?nRF*rRbfTE+A!8bJzRA_-1C5b7CC5a5a`6;O&tMl_<%={t+ z=ltB<)Vz{nBq4ASnTevRxU{$+HLn;V2=^W+H%`70m@J1V##4(Gl1qz`K2ZLk+VRcP0L?446v|0m| zy=9pxsVN|lf_zZ1n3K5-Dl;cDF;5{NA1s|(oT|wXkYAh$iU_O8W?`iwspVD-0Y#~0nfax~3;{)% zWr@j^lh=i{vq9>v&HCYTj0%W`OEE)GY7V%xEY8R*0P%A3OHwCCMCh|SK>W11GGZs= zWV@)>>WO8kDGb3NQUP4)G6aL0Hc(0-H3jU9;>mi^3c{fJMF;E|9R*Nv1S(M-qBVH( z!TCH9EHgPi+CvFaS_G%&q$Y!EW^g)V2u{sOgV$q|S4IElFDg+;K`KioFO9LVD@uiw zaq0PqIiQ%zEhtgQ%u`59O--?42+qhahvj_;yA-9Uwc30=W;-JXIM;!4b6cFeqe5u` zDEk#dN}lTcq%1vH(-u^L*D?f`B$kvGTS4j6VmLzqRJf+5OkNh3$qQjZ?Vc%OF`*EM*&o(CgLVj9FYMw%IMq*KF3Me*{ zGZORCQx!52^HPfS6g=zGz%3!Lkswx)LVkIkf@gpZhy!VMLA?yBHo=8Fq>Tm2-rzi< z#}Hbas*sbJn^|H7Vx~YFWf`dou&fDcVHbeXb!s`t5qSz(`I&j3R90T8Rg|ljoS&w1u{^K(=4^HLQ`iZWA+L2idM`%{Y`VVsz!04ZP) zO-@KrqXUY`#AI;O3K9lMsS3$Osi3yDohM?pNZgzqjsfh&zsfk4jC4Bh` z8Hr`73g!7l*{LadlW(PH3Ww(xWfwDmNtkhynNlazLqgv(K%oc}H^tCscJ_1$QYfy> zD@m--V~ETz1tmWPP)LB<2cYOFQgF}DPXXnmVo=qS2ub>&1~0tzl~GbsP;8~IUtV6W zmkv`53UGZ$bm(X17UTyPl_)8cBo?Kome?xAC*>sOWh*HZrRLZw<>iCAbE!p2cAlVQ zR-*4(0gf9`*$ArDKn-kgTNdFEXs}K0NIl36E+2{&DpN}oC!40(dM2fUdyb$6LJGpM zN^sXg8;9{|jYVj03}m4aq%zx_k!H^XZEP*b_{9lpN?T2yk{OheoLT^Cm4O`w&S~H> z5)}WSbO$j(fh1cQ!09cOAu%N-HAMl`d76AMN6rhmO9k#lf$RWV3#w&NtN;lh`3uYi zl}no7{+QBafh@Jn0$F{GlUHY}X(X3IYGQ?w%7RoD|AN#!hEyj|FBnuzr=}>VYJiG5 z&Em<+a?0vK1rKJxf?WYAnMm^~$T&zDkpk{JA(h;q*v5#fdfbu4fNmDZ!&nU=!Hfb( zwWyGjT9%rlkd|LxgwfYP3TJQ#Af+F$lR&8;H3gD`zzR@e3M_)h2qmx?IjLzSU=!-e zN>7=2&=dtupAg4@5)a5};9v*4f*5y6fd@3ed4nM*vA6_MG^R4-WM)rJ%vPSPX06T) zWB<-Zu>JDXpyGO)4RaqdPCk&MHrYO(b@G86)y?_&jEs{j3!aK1`Z$Rx;64c~?blN; z?K6P7PoSj1P@P!|sw;~bp08_ovUl>69c!OWYgf<+&de>y$xO>kO;K>p$jk#boa~?P zY<#(T3QS2zQ6i)TlbC~06Ht_&m6}|l>zSe(mRbaApIU+2z~z-ixsw|T_3I4{bq&oG z3@xlojJSLfi%WDviW2jRa}rDPi>wrU^Gl0U6@pSz%Tg6=azUIT5Zj?BvpBW1Krb(~ z#E#1+F)zI|F+Ei`BsDSD3TCqc!ohGARti-aT)v*Zt_Y_XPS!8VuaD4mF3K-Y$;{J* zIv3$aE(|$cPZui%6LU)=V@o7Sm@7bb=sNo$$+%_aq*^KHM?>n`qFmkL{N&8U96cC6 zR>2-LW}}~zpPZPJs-Kz{9~!Lh;~ekn8XWBC?i#G0l9ia3p08Jsk7g*?A%>==#*^n3 znJ2&+THp#(vsmHT+=VZj8eXj5{$l<1XB(Ta4EH^oyYT70)~8Eao=<3d*0uEM#4ap~ zo=)g}K4rzTj_s506v^sij{iNIv*yXpWzRSEGN@{x4);BqF@N&6qNQS>R0VR+<`qxd zdY*3I^t5&J%js(;&nV788RmO7Vb1d{i#9Ws6fz3G-_xP00UdAAELK&0zo&C@VX2&q z#?$`wFB>{F8Q$;dc)n&0e3Vb&<-)C#HcbGjk^dB3L3q7R{n_RfHu|Z#n=LDzGfp#!i5nP~V<^mWhHE_u3Z%JV5JK(bpK zU$*zZY~K5HL)()*vz|@a1`0mVINU%2k+x>+xl zH9qZF@N(u7{DXN4&u6tf-7(>5|MsU7roZ1a|Jm9l&nEXi**oXSj@}o|dtWSC{cO^b zms1)ZH#C8g^S;SXTbF|DnAP%hecST|jn5aZd$Dc_#HMGHd-Xs%cQ1Xud-?O-Yacf> zF+A;Uf4Zxm;rYycPdnP4t)F7W0P^SJ4Ulv@`D;z#V#?lUYZgA6 zy1{Dm*V>PalRwvYn76e)UAOba+GU^|@)U_<#Q@=1F+A(s_hd)!(~b>Kdv?BT?R`G0 z<;l)vlPepP*q-lO@_cv8Q>(BGWZdulo{p#cw!c`v7Lo!_3Jl{R}+1&ZhrZ0UqXFdwYioq2!O89j%J9B2vOLmA;^HG`=9r(ecm|}YRnVXUENQ1Z=3wPMQ*cN>q18D7mHh8 ztXuSaciW4uCM$+#3-&zS(~mTU2rBG0Plafne6G#4{^{&}Pn-LnZs>opehb6%-7W9; zbbwp`pkfdbVbA*eU+mw&0O35H(EEJ(1}i8JQf55uU;kwHQfR5NbK8^MeURXJvSaP@ z<-1?bTmn@MrI1GvH93kIo^RUsVsYzap>~z}r#sd??OMt3WbcBfOZPsV*zkT&55vn@ z6JAX3f3d&)+3qDzXRd(qAwk6OWXJB83%5e4XVbU6oWAAxuKl3#L`VUK99sxcD+bSC zCqD&40~o^?!kFC9K6A2KhaTIWhNsKBttMA@Sg<|YvioV*ipgs_BJ7^_?0U9tD|nzW zHLnCd?g*(d86Xt2;zZ_vQt6yER+HsBS56k`QsRBKW%rBi&5(p*HCeyQE8uDC<|n)Q zK(!2FToIK27+&n3{bWbOv$ab>RmJkfs45sBwFsorV0hWk@U(pwB$6hd?o!`u+U?Ca znSY9g03;JLK&Yn^XH2f|(V0A@N2?xO;6ozs>6{f1t&mda`Nm#&6hh;5QV%3cLsBfm zv;GNB`@0yPwl+VTy5U*xI)*2^H@#Tg$nbpj#HZ`$Kb<(^#rl>P>vlnfpH7?s(T&7! zWC0Z)lkfI4$UL9D?rCQ)v_bMhj3)bp}w z9VmZ7@;}6|Cwmu6RxB3wc?LHCTIqr7&S(7-p6r|bY~qX;>ozbTl=QEE(YzN_dx678 z0b`U=vCo;2?d8I)&lfaKPU`>4_OhY#<-(nl!zL^c-?{n4;#LMo4P(UsZzxUvGeKPt zR7&k^g#-h*UW3F8Xp&%Zue5APX9vcJ_jD#Pj8ilNl!!uz`|5XUFD(N#cwm&%li*hNrEYpKspH z@M8a*=d0IG?wzc`2g#HQu%X6vlUFfLPMx|o^6BXRnIymLc(lv$2i4>goF!nYva?j+-g&h&cucYHdI? zKbyVf*|ZG|5RMg;h85ehS|H++Yi7psK}vGC(8HN`H=mv*%P0?NraYUz;MwM>@Ma3b zv$abg;X1jnLUgiiGuLF^If~Nosvnx1ckh0(cPcbYwdR}=YS{g3>IMc#fIb6rCV!b@ z&jyLU$vSiWc_48ODUK#r&2_2=wT3pVc-GqYWbgjxQ&u1{8l9Faxb@}SMWE&w z#1SuNPI%g}&5GgaoE1nTk&uB%g(o|@Ao&8)uzfat8${FNh9*$GKV|*1o<;=^VbI{@ zvyN#Bu+d3S1N7uv6COxzftL2)=I&<$6)=0JZeBN!g^~H`#1)e_&bO`KJNen1&L_Ke zy;wi>>Fj+F^Fgf`aG3*Y(@xp?bnOI4K?F5$`ZiEl?U?YaV>_r7yrcKYo>`zk0ypK} z@9BB6w+*85#s2o^E4rW0>3*?w`?I-ApX{0Sw7LJ;jP;;8wrl>AU2V^2akV^Ku>I-U z2_QGWnQtyK=jr4|SUYf5%agqz{$zy(GwLBOQveS{zF5EZ+2*Ow<}Q7)fA))oJ)j7C zwr(ptCPASK3Vd)K{$zI_qWMVF5G2+SNH5eO$fxV~JZ)X752D(4LE;otyD2=`(fwlY zUQj|=zvpTDu4hf4J_CGcQ~_MEOkTC%oC-(=Ttz(HFbh;pcP|A+12{84$_`MkrF@~j z7sw;qH$C6o|6(0BIaRdu2~{wZX?M1Ccv`p#Gkn z!qbio&@K(Qlva4uFb8Rr4?I$dXxf9hh^GCchPj(1mQG=uylt7f+Mb4IQ}!`D2PfVq zJC}j;7i_3f;pz5GkaqCo9m^Bzw{L<3EyUMk`4JMvPuq7ffC|$oJHft0TXleI7_VMG z(GFA?Luvpr41nr~G-FBEUk^^W&u6u~oHgP3^2X=8mOt%S%>Wvp07p9{R3K4FTG&9_ zZ}9Yl!;Ja@Tp^>MXr~12l0loIpv(Yv6%MoT8})2X!_x_U(B$}Z+MH)=7CqV3HhD|A z(Byf`1tw2ep*gu}xz6MXE957uEuXSkcLgKUWQ$d5lap3!O`f#sz~rRWS45uf-t}VL zI*^~hBM$JijAaax!nCaLWXD=)JqQ}%0F6gJTeA>S45AE5GJu93rD5Zbpdq21jqnjm HP@e|?taKE= diff --git a/locale/zh_Hant/LC_MESSAGES/django.mo b/locale/zh_Hant/LC_MESSAGES/django.mo index f46e61fc0013b7807b09af06f48c5b61e1d46597..f9ca27be9b891b3b13c30e68d084e0cd54184a43 100644 GIT binary patch delta 14268 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 delta 13392 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 F0RZ4j_uc>i From 40e4591a24b4ce4663bf5ea9e95e3b54adfb2119 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 24 Nov 2021 11:59:45 +0100 Subject: [PATCH 079/217] Apply review suggestions --- bookwyrm/forms.py | 9 +-- .../migrations/0119_user_feed_status_types.py | 15 ++++- bookwyrm/models/user.py | 17 ++++- bookwyrm/templates/feed/feed.html | 5 +- bookwyrm/views/feed.py | 26 ++++---- locale/en_US/LC_MESSAGES/django.po | 65 +++++++++---------- 6 files changed, 79 insertions(+), 58 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index f52cbeb31..249b92113 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -9,6 +9,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from bookwyrm import models +from bookwyrm.models.user import FeedFilterChoices class CustomForm(ModelForm): @@ -179,15 +180,9 @@ class FeedStatusTypesForm(CustomForm): model = models.User fields = ["feed_status_types"] help_texts = {f: None for f in fields} - labels = {"feed_status_types": ""} widgets = { "feed_status_types": widgets.CheckboxSelectMultiple( - choices=[ - ("review", _("Reviews")), - ("comment", _("Comments")), - ("quotation", _("Quotations")), - ("everything", _("Everything else")), - ], + choices=FeedFilterChoices, ), } diff --git a/bookwyrm/migrations/0119_user_feed_status_types.py b/bookwyrm/migrations/0119_user_feed_status_types.py index d5c0f321f..64fa91697 100644 --- a/bookwyrm/migrations/0119_user_feed_status_types.py +++ b/bookwyrm/migrations/0119_user_feed_status_types.py @@ -1,5 +1,6 @@ -# Generated by Django 3.2.5 on 2021-11-21 23:28 +# Generated by Django 3.2.5 on 2021-11-24 10:15 +import bookwyrm.models.user import django.contrib.postgres.fields from django.db import migrations, models @@ -15,8 +16,16 @@ class Migration(migrations.Migration): model_name="user", name="feed_status_types", field=django.contrib.postgres.fields.ArrayField( - base_field=models.CharField(max_length=10), - default=["review", "comment", "quotation", "everything"], + base_field=models.CharField( + choices=[ + ("review", "Reviews"), + ("comment", "Comments"), + ("quotation", "Quotations"), + ("everything", "Everything else"), + ], + max_length=10, + ), + default=bookwyrm.models.user.get_feed_filter_choices, size=8, ), ), diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index 7ca92e4f2..f4183812b 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -9,6 +9,7 @@ from django.core.validators import MinValueValidator from django.dispatch import receiver from django.db import models, transaction from django.utils import timezone +from django.utils.translation import gettext_lazy as _ from model_utils import FieldTracker import pytz @@ -27,6 +28,18 @@ from .federated_server import FederatedServer from . import fields, Review +FeedFilterChoices = [ + ("review", _("Reviews")), + ("comment", _("Comments")), + ("quotation", _("Quotations")), + ("everything", _("Everything else")), +] + + +def get_feed_filter_choices(): + return [f[0] for f in FeedFilterChoices] + + def site_link(): """helper for generating links to the site""" protocol = "https" if USE_HTTPS else "http" @@ -130,9 +143,9 @@ class User(OrderedCollectionPageMixin, AbstractUser): # feed options feed_status_types = ArrayField( - models.CharField(max_length=10, blank=False), + models.CharField(max_length=10, blank=False, choices=FeedFilterChoices), size=8, - default=list(["review", "comment", "quotation", "everything"]), + default=get_feed_filter_choices, ) preferred_timezone = models.CharField( diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 14df11c68..0579610b6 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -42,7 +42,7 @@ -
+
@@ -69,7 +69,8 @@ {# activity feed #} {% if not activities %}
-

{% trans "There aren't any activities right now! Try following a user to get started" %}{% if user.feed_status_types|length < 4 %}{% trans ", or enable more status types" %}{% endif %}

+

{% trans "There aren't any activities right now! Try following a user to get started" %}

+

{% if user.feed_status_types|length < 4 %}{% trans "Alternatively, you can try enabling more status types" %}{% endif %}

{% if request.user.show_suggested_users and suggested_users %} {# suggested users for when things are very lonely #} diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 3ac3f5914..0b2b35006 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -7,10 +7,10 @@ from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse from django.utils import timezone from django.utils.decorators import method_decorator -from django.utils.translation import gettext_lazy as _ from django.views import View from bookwyrm import activitystreams, forms, models +from bookwyrm.models.user import FeedFilterChoices from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH, STREAMS from bookwyrm.suggested_users import suggested_users @@ -58,12 +58,7 @@ class Feed(View): "tab": tab, "streams": STREAMS, "goal_form": forms.GoalForm(), - "feed_status_types_options": [ - ("review", _("Reviews")), - ("comment", _("Comments")), - ("quotation", _("Quotations")), - ("everything", _("Everything else")), - ], + "feed_status_types_options": FeedFilterChoices, "settings_saved": settings_saved, "path": f"/{tab['key']}", }, @@ -260,12 +255,21 @@ def filter_stream_by_status_type(activities, allowed_types=None): allowed_types = [] if "review" not in allowed_types: - activities = activities.filter(Q(review__isnull=True)) + activities = activities.filter( + Q(review__isnull=True) | Q(boost__boosted_status__review__isnull=True) + ) if "comment" not in allowed_types: - activities = activities.filter(Q(comment__isnull=True)) + activities = activities.filter( + Q(comment__isnull=True) | Q(boost__boosted_status__comment__isnull=True) + ) if "quotation" not in allowed_types: - activities = activities.filter(Q(quotation__isnull=True)) + activities = activities.filter( + Q(quotation__isnull=True) | Q(boost__boosted_status__quotation__isnull=True) + ) if "everything" not in allowed_types: - activities = activities.filter(Q(generatednote__isnull=True)) + activities = activities.filter( + Q(generatednote__isnull=True) + | Q(boost__boosted_status__generatednote__isnull=True) + ) return activities diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index 0237d1a8a..c89e395e5 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-22 18:23+0000\n" +"POT-Creation-Date: 2021-11-24 10:57+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -18,75 +18,58 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: bookwyrm/forms.py:186 bookwyrm/templates/book/book.html:218 -#: bookwyrm/views/feed.py:62 -msgid "Reviews" -msgstr "" - -#: bookwyrm/forms.py:187 bookwyrm/views/feed.py:63 -msgid "Comments" -msgstr "" - -#: bookwyrm/forms.py:188 bookwyrm/views/feed.py:64 -msgid "Quotations" -msgstr "" - -#: bookwyrm/forms.py:189 bookwyrm/views/feed.py:65 -msgid "Everything else" -msgstr "" - -#: bookwyrm/forms.py:266 +#: bookwyrm/forms.py:262 msgid "A user with this email already exists." msgstr "" -#: bookwyrm/forms.py:280 +#: bookwyrm/forms.py:276 msgid "One Day" msgstr "" -#: bookwyrm/forms.py:281 +#: bookwyrm/forms.py:277 msgid "One Week" msgstr "" -#: bookwyrm/forms.py:282 +#: bookwyrm/forms.py:278 msgid "One Month" msgstr "" -#: bookwyrm/forms.py:283 +#: bookwyrm/forms.py:279 msgid "Does Not Expire" msgstr "" -#: bookwyrm/forms.py:287 +#: bookwyrm/forms.py:283 #, python-brace-format msgid "{i} uses" msgstr "" -#: bookwyrm/forms.py:288 +#: bookwyrm/forms.py:284 msgid "Unlimited" msgstr "" -#: bookwyrm/forms.py:356 +#: bookwyrm/forms.py:352 msgid "List Order" msgstr "" -#: bookwyrm/forms.py:357 +#: bookwyrm/forms.py:353 msgid "Book Title" msgstr "" -#: bookwyrm/forms.py:358 bookwyrm/templates/shelf/shelf.html:149 +#: bookwyrm/forms.py:354 bookwyrm/templates/shelf/shelf.html:149 #: bookwyrm/templates/shelf/shelf.html:181 #: bookwyrm/templates/snippets/create_status/review.html:33 msgid "Rating" msgstr "" -#: bookwyrm/forms.py:360 bookwyrm/templates/lists/list.html:110 +#: bookwyrm/forms.py:356 bookwyrm/templates/lists/list.html:110 msgid "Sort By" msgstr "" -#: bookwyrm/forms.py:364 +#: bookwyrm/forms.py:360 msgid "Ascending" msgstr "" -#: bookwyrm/forms.py:365 +#: bookwyrm/forms.py:361 msgid "Descending" msgstr "" @@ -170,6 +153,22 @@ msgstr "" msgid "A user with that username already exists." msgstr "" +#: bookwyrm/models/user.py:32 bookwyrm/templates/book/book.html:218 +msgid "Reviews" +msgstr "" + +#: bookwyrm/models/user.py:33 +msgid "Comments" +msgstr "" + +#: bookwyrm/models/user.py:34 +msgid "Quotations" +msgstr "" + +#: bookwyrm/models/user.py:35 +msgid "Everything else" +msgstr "" + #: bookwyrm/settings.py:118 msgid "Home Timeline" msgstr "" @@ -1108,8 +1107,8 @@ msgstr "" msgid "There aren't any activities right now! Try following a user to get started" msgstr "" -#: bookwyrm/templates/feed/feed.html:72 -msgid ", or enable more status types" +#: bookwyrm/templates/feed/feed.html:73 +msgid "Alternatively, you can try enabling more status types" msgstr "" #: bookwyrm/templates/feed/goal_card.html:6 From 2ad37a22dde853492743e129718b961b31175e18 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 24 Nov 2021 13:37:09 +0100 Subject: [PATCH 080/217] Move stream filter to helpers --- bookwyrm/views/feed.py | 28 +--------------------------- bookwyrm/views/helpers.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 0b2b35006..bd39b0834 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -14,7 +14,7 @@ from bookwyrm.models.user import FeedFilterChoices from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH, STREAMS from bookwyrm.suggested_users import suggested_users -from .helpers import get_user_from_username +from .helpers import filter_stream_by_status_type, get_user_from_username from .helpers import is_api_request, is_bookwyrm_request @@ -247,29 +247,3 @@ def get_suggested_books(user, max_books=5): suggested_books.append(shelf_preview) book_count += len(shelf_preview["books"]) return suggested_books - - -def filter_stream_by_status_type(activities, allowed_types=None): - """filter out activities based on types""" - if not allowed_types: - allowed_types = [] - - if "review" not in allowed_types: - activities = activities.filter( - Q(review__isnull=True) | Q(boost__boosted_status__review__isnull=True) - ) - if "comment" not in allowed_types: - activities = activities.filter( - Q(comment__isnull=True) | Q(boost__boosted_status__comment__isnull=True) - ) - if "quotation" not in allowed_types: - activities = activities.filter( - Q(quotation__isnull=True) | Q(boost__boosted_status__quotation__isnull=True) - ) - if "everything" not in allowed_types: - activities = activities.filter( - Q(generatednote__isnull=True) - | Q(boost__boosted_status__generatednote__isnull=True) - ) - - return activities diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index f28d01023..173cb85b5 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -6,6 +6,7 @@ import dateutil.tz from dateutil.parser import ParserError from requests import HTTPError +from django.db.models import Q from django.http import Http404 from django.utils import translation @@ -153,3 +154,29 @@ def set_language(user, response): translation.activate(user.preferred_language) response.set_cookie(settings.LANGUAGE_COOKIE_NAME, user.preferred_language) return response + + +def filter_stream_by_status_type(activities, allowed_types=None): + """filter out activities based on types""" + if not allowed_types: + allowed_types = [] + + if "review" not in allowed_types: + activities = activities.filter( + Q(review__isnull=True), Q(boost__boosted_status__review__isnull=True) + ) + if "comment" not in allowed_types: + activities = activities.filter( + Q(comment__isnull=True), Q(boost__boosted_status__comment__isnull=True) + ) + if "quotation" not in allowed_types: + activities = activities.filter( + Q(quotation__isnull=True), Q(boost__boosted_status__quotation__isnull=True) + ) + if "everything" not in allowed_types: + activities = activities.filter( + Q(generatednote__isnull=True), + Q(boost__boosted_status__generatednote__isnull=True), + ) + + return activities From db5e7a886aacb18cf4b4f5990a32768a619296b9 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 24 Nov 2021 19:00:30 +0100 Subject: [PATCH 081/217] Handle count of notifications banner --- bookwyrm/activitystreams.py | 37 ++++++++++++++++++++++++++++++- bookwyrm/static/js/bookwyrm.js | 35 ++++++++++++++++++++++++++++- bookwyrm/templates/feed/feed.html | 1 + bookwyrm/views/feed.py | 1 + bookwyrm/views/updates.py | 7 +++++- 5 files changed, 78 insertions(+), 3 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index e1a52d263..4cba9939e 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -22,6 +22,11 @@ class ActivityStream(RedisStore): stream_id = self.stream_id(user) return f"{stream_id}-unread" + def unread_by_status_type_id(self, user): + """the redis key for this user's unread count for this stream""" + stream_id = self.stream_id(user) + return f"{stream_id}-unread-by-type" + def get_rank(self, obj): # pylint: disable=no-self-use """statuses are sorted by date published""" return obj.published_date.timestamp() @@ -35,6 +40,10 @@ class ActivityStream(RedisStore): for user in self.get_audience(status): # add to the unread status count pipeline.incr(self.unread_id(user)) + # add to the unread status count for status type + pipeline.hincrby( + self.unread_by_status_type_id(user), get_status_type(status), 1 + ) # and go! pipeline.execute() @@ -55,6 +64,7 @@ class ActivityStream(RedisStore): """load the statuses to be displayed""" # clear unreads for this feed r.set(self.unread_id(user), 0) + r.delete(self.unread_by_status_type_id(user)) statuses = self.get_store(self.stream_id(user)) return ( @@ -75,6 +85,14 @@ class ActivityStream(RedisStore): """get the unread status count for this user's feed""" return int(r.get(self.unread_id(user)) or 0) + def get_unread_count_by_status_type(self, user): + """get the unread status count for this user's feed's status types""" + status_types = r.hgetall(self.unread_by_status_type_id(user)) + return { + str(key.decode("utf-8")): int(value) or 0 + for key, value in status_types.items() + } + def populate_streams(self, user): """go from zero to a timeline""" self.populate_store(self.stream_id(user)) @@ -460,7 +478,7 @@ def remove_status_task(status_ids): @app.task(queue=HIGH) def add_status_task(status_id, increment_unread=False): """add a status to any stream it should be in""" - status = models.Status.objects.get(id=status_id) + status = models.Status.objects.select_subclasses().get(id=status_id) # we don't want to tick the unread count for csv import statuses, idk how better # to check than just to see if the states is more than a few days old if status.created_date < timezone.now() - timedelta(days=2): @@ -507,3 +525,20 @@ def handle_boost_task(boost_id): stream.remove_object_from_related_stores(boosted, stores=audience) for status in old_versions: stream.remove_object_from_related_stores(status, stores=audience) + + +def get_status_type(status): + """return status type even for boosted statuses""" + status_type = status.status_type.lower() + + # Check if current status is a boost + if hasattr(status, "boost"): + # Act in accordance of your findings + if hasattr(status.boost.boosted_status, "review"): + status_type = "review" + if hasattr(status.boost.boosted_status, "comment"): + status_type = "comment" + if hasattr(status.boost.boosted_status, "quotation"): + status_type = "quotation" + + return status_type diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 2d5b88adc..b45578000 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -113,9 +113,42 @@ let BookWyrm = new class { * @return {undefined} */ updateCountElement(counter, data) { + let count = data.count; + const count_by_type = data.count_by_type; const currentCount = counter.innerText; - const count = data.count; const hasMentions = data.has_mentions; + const allowedStatusTypesEl = document.getElementById('unread-notifications-wrapper'); + + // If we're on the right counter element + if (counter.closest('[data-poll-wrapper]').contains(allowedStatusTypesEl)) { + const allowedStatusTypes = JSON.parse(allowedStatusTypesEl.textContent); + + // For keys in common between allowedStatusTypes and count_by_type + // This concerns 'review', 'quotation', 'comment' + count = allowedStatusTypes.reduce(function(prev, currentKey) { + const currentValue = count_by_type[currentKey] | 0; + return prev + currentValue; + }, 0); + + // Add all the "other" in count_by_type if 'everything' is allowed + if (allowedStatusTypes.includes('everything')) { + // Clone count_by_type with 0 for reviews/quotations/comments + const count_by_everything_else = Object.assign( + {}, + count_by_type, + {review: 0, quotation: 0, comment: 0} + ); + + count = Object.keys(count_by_everything_else).reduce( + function(prev, currentKey) { + const currentValue = + count_by_everything_else[currentKey] | 0 + return prev + currentValue; + }, + count + ); + } + } if (count != currentCount) { this.addRemoveClass(counter.closest('[data-poll-wrapper]'), 'is-hidden', count < 1); diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 0579610b6..1a2488afe 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -54,6 +54,7 @@ {% if not activities.number > 1 %} {% if request.user.show_goal and not goal and tab.key == 'home' %} diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index bd39b0834..7cf56d48f 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -59,6 +59,7 @@ class Feed(View): "streams": STREAMS, "goal_form": forms.GoalForm(), "feed_status_types_options": FeedFilterChoices, + "allowed_status_types": request.user.feed_status_types, "settings_saved": settings_saved, "path": f"/{tab['key']}", }, diff --git a/bookwyrm/views/updates.py b/bookwyrm/views/updates.py index 726145626..2bbc54776 100644 --- a/bookwyrm/views/updates.py +++ b/bookwyrm/views/updates.py @@ -22,4 +22,9 @@ def get_unread_status_count(request, stream="home"): stream = activitystreams.streams.get(stream) if not stream: return JsonResponse({}) - return JsonResponse({"count": stream.get_unread_count(request.user)}) + return JsonResponse( + { + "count": stream.get_unread_count(request.user), + "count_by_type": stream.get_unread_count_by_status_type(request.user), + } + ) From 8712b2fdab12dc4ab059575432d6fef62011485e Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 24 Nov 2021 19:02:07 +0100 Subject: [PATCH 082/217] ESLint --- bookwyrm/static/js/bookwyrm.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index b45578000..a5f7d7e96 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -127,6 +127,7 @@ let BookWyrm = new class { // This concerns 'review', 'quotation', 'comment' count = allowedStatusTypes.reduce(function(prev, currentKey) { const currentValue = count_by_type[currentKey] | 0; + return prev + currentValue; }, 0); @@ -143,6 +144,7 @@ let BookWyrm = new class { function(prev, currentKey) { const currentValue = count_by_everything_else[currentKey] | 0 + return prev + currentValue; }, count From 0001d6e92a2c4107188c5b7cdf618df35fcfc0ae Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 24 Nov 2021 19:04:14 +0100 Subject: [PATCH 083/217] PyLint --- bookwyrm/models/user.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index f4183812b..4d98f5c57 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -37,6 +37,7 @@ FeedFilterChoices = [ def get_feed_filter_choices(): + """return a list of filter choice keys""" return [f[0] for f in FeedFilterChoices] From 5f81be74cb3beb0a8392d7f96e55b86d3ae7726f Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 24 Nov 2021 20:52:30 +0100 Subject: [PATCH 084/217] Add test --- bookwyrm/tests/views/test_updates.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bookwyrm/tests/views/test_updates.py b/bookwyrm/tests/views/test_updates.py index 27181fc95..d510fba63 100644 --- a/bookwyrm/tests/views/test_updates.py +++ b/bookwyrm/tests/views/test_updates.py @@ -50,10 +50,13 @@ class UpdateViews(TestCase): request = self.factory.get("") request.user = self.local_user - with patch("bookwyrm.activitystreams.ActivityStream.get_unread_count") as mock: - mock.return_value = 3 - result = views.get_unread_status_count(request, "home") + with patch("bookwyrm.activitystreams.ActivityStream.get_unread_count") as mock_count: + with patch("bookwyrm.activitystreams.ActivityStream.get_unread_count_by_status_type") as mock_count_by_status: + mock_count.return_value = 3 + mock_count_by_status.return_value = {"review": 5} + result = views.get_unread_status_count(request, "home") self.assertIsInstance(result, JsonResponse) data = json.loads(result.getvalue()) self.assertEqual(data["count"], 3) + self.assertEqual(data["count_by_type"]["review"], 5) From 7d24568dcda7cbec7af3647ab33b46e7b9fab457 Mon Sep 17 00:00:00 2001 From: Joachim Date: Wed, 24 Nov 2021 20:54:53 +0100 Subject: [PATCH 085/217] Update test_updates.py --- bookwyrm/tests/views/test_updates.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/views/test_updates.py b/bookwyrm/tests/views/test_updates.py index d510fba63..e7b466ccf 100644 --- a/bookwyrm/tests/views/test_updates.py +++ b/bookwyrm/tests/views/test_updates.py @@ -50,8 +50,12 @@ class UpdateViews(TestCase): request = self.factory.get("") request.user = self.local_user - with patch("bookwyrm.activitystreams.ActivityStream.get_unread_count") as mock_count: - with patch("bookwyrm.activitystreams.ActivityStream.get_unread_count_by_status_type") as mock_count_by_status: + with patch( + "bookwyrm.activitystreams.ActivityStream.get_unread_count" + ) as mock_count: + with patch( + "bookwyrm.activitystreams.ActivityStream.get_unread_count_by_status_type" + ) as mock_count_by_status: mock_count.return_value = 3 mock_count_by_status.return_value = {"review": 5} result = views.get_unread_status_count(request, "home") From c704c7eb8f485e0776577718142d29e8f150e500 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Thu, 25 Nov 2021 07:38:08 +1100 Subject: [PATCH 086/217] remove from any shelf in all books shelf view - fixes removing book from 'all books' shelf erroring - remove from any shelf item is on when in 'all books' --- .../templates/snippets/shelf_selector.html | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/bookwyrm/templates/snippets/shelf_selector.html b/bookwyrm/templates/snippets/shelf_selector.html index 1a2c46d01..663bd5633 100644 --- a/bookwyrm/templates/snippets/shelf_selector.html +++ b/bookwyrm/templates/snippets/shelf_selector.html @@ -53,15 +53,30 @@ {% endwith %} {% endif %} {% endfor %} - + +{% if shelf.identifier == 'all' %} +{% for shelved_in in book.shelves.all %} + +{% endfor %} +{% else %} + + +{% 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 %} From b91915d31680b71864ba14cc686442fb58a2c9c1 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Thu, 25 Nov 2021 08:20:34 +1100 Subject: [PATCH 087/217] change shelf var for shelf_selector in book view --- bookwyrm/templates/book/book.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html index 1eb08001d..713e7abee 100644 --- a/bookwyrm/templates/book/book.html +++ b/bookwyrm/templates/book/book.html @@ -162,7 +162,7 @@
  • {% blocktrans with path=shelf.shelf.local_path shelf_name=shelf.shelf.name %}{{ shelf_name }}{% endblocktrans %}
    - {% include 'snippets/shelf_selector.html' with current=shelf.shelf class="is-small" readthrough=readthrough %} + {% include 'snippets/shelf_selector.html' with shelf=shelf.shelf class="is-small" readthrough=readthrough %}
  • {% endfor %} From 5b67226571d85d281e3ccedc2710084ffceb2201 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Thu, 25 Nov 2021 19:12:03 +1100 Subject: [PATCH 088/217] forceReload prevents ajax submission ...instead of weird hacky workarounds forcing refreshes later. --- bookwyrm/static/js/status_cache.js | 8 +------- bookwyrm/views/reading.py | 2 -- bookwyrm/views/shelf/shelf_actions.py | 2 -- bookwyrm/views/status.py | 4 ---- 4 files changed, 1 insertion(+), 15 deletions(-) diff --git a/bookwyrm/static/js/status_cache.js b/bookwyrm/static/js/status_cache.js index f179aa7d9..1ec72b3cb 100644 --- a/bookwyrm/static/js/status_cache.js +++ b/bookwyrm/static/js/status_cache.js @@ -74,7 +74,7 @@ let StatusCache = new class { // This allows the form to submit in the old fashioned way if there's a problem - if (!trigger || !form) { + if (!trigger || !form || response.headers.get("forceReload")) { return; } @@ -90,12 +90,6 @@ let StatusCache = new class { trigger.removeAttribute('disabled'); }) .then(response => { - if (response.headers.get("forceReload")) { - BookWyrm.addRemoveClass(form, 'is-processing', true); - trigger.setAttribute('disabled', null); - - return location.reload(); - } if (!response.ok) { throw new Error(); diff --git a/bookwyrm/views/reading.py b/bookwyrm/views/reading.py index 75a45f245..a91fa8e7a 100644 --- a/bookwyrm/views/reading.py +++ b/bookwyrm/views/reading.py @@ -102,8 +102,6 @@ class ReadingStatus(View): != desired_shelf.identifier ): return unshelve(request, referer=referer, book_id=book_id) - # don't try to unshelve a read status shelf: it has already been deleted. - return HttpResponse(headers={"forceReload": "true"}) if is_api_request(request): return HttpResponse() diff --git a/bookwyrm/views/shelf/shelf_actions.py b/bookwyrm/views/shelf/shelf_actions.py index 77053f534..3fff92a6a 100644 --- a/bookwyrm/views/shelf/shelf_actions.py +++ b/bookwyrm/views/shelf/shelf_actions.py @@ -101,6 +101,4 @@ def unshelve(request, referer=None, book_id=False): ) shelf_book.raise_not_deletable(request.user) shelf_book.delete() - if bool(referer): - return HttpResponse(headers={"forceReload": "true"}) return redirect(request.headers.get("Referer", "/")) diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index 144408b50..bb69d30c0 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -125,10 +125,6 @@ class CreateStatus(View): except Http404: pass - # force page reload if this was triggered from 'move' button - if bool(request.POST.get("shelf")): - return HttpResponse(headers={"forceReload": "true"}) - if is_api_request(request): return HttpResponse() return redirect("/") From 951eb43aa657d9ced537b078bf14286520b18a66 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Fri, 26 Nov 2021 17:16:26 +1100 Subject: [PATCH 089/217] bypass ajax for shelf_selector statuses --- bookwyrm/static/js/status_cache.js | 3 +-- .../snippets/reading_modals/finish_reading_modal.html | 2 +- .../snippets/reading_modals/start_reading_modal.html | 2 +- .../snippets/reading_modals/want_to_read_modal.html | 2 +- bookwyrm/templates/snippets/shelf_selector.html | 6 +++--- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bookwyrm/static/js/status_cache.js b/bookwyrm/static/js/status_cache.js index 1ec72b3cb..418b7dee2 100644 --- a/bookwyrm/static/js/status_cache.js +++ b/bookwyrm/static/js/status_cache.js @@ -74,7 +74,7 @@ let StatusCache = new class { // This allows the form to submit in the old fashioned way if there's a problem - if (!trigger || !form || response.headers.get("forceReload")) { + if (!trigger || !form) { return; } @@ -90,7 +90,6 @@ let StatusCache = new class { trigger.removeAttribute('disabled'); }) .then(response => { - if (!response.ok) { throw new Error(); } diff --git a/bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html b/bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html index 79542b29a..a35ed9e0b 100644 --- a/bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html +++ b/bookwyrm/templates/snippets/reading_modals/finish_reading_modal.html @@ -9,7 +9,7 @@ Finish "{{ book_title }}" {% endblock %} {% block modal-form-open %} -
    + {% csrf_token %} diff --git a/bookwyrm/templates/snippets/reading_modals/start_reading_modal.html b/bookwyrm/templates/snippets/reading_modals/start_reading_modal.html index 03ebd9003..423f77ebe 100644 --- a/bookwyrm/templates/snippets/reading_modals/start_reading_modal.html +++ b/bookwyrm/templates/snippets/reading_modals/start_reading_modal.html @@ -9,7 +9,7 @@ Start "{{ book_title }}" {% endblock %} {% block modal-form-open %} - + {% csrf_token %} diff --git a/bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html b/bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html index 2fc2a012d..2fb976bf1 100644 --- a/bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html +++ b/bookwyrm/templates/snippets/reading_modals/want_to_read_modal.html @@ -9,7 +9,7 @@ Want to Read "{{ book_title }}" {% endblock %} {% block modal-form-open %} - + {% csrf_token %} diff --git a/bookwyrm/templates/snippets/shelf_selector.html b/bookwyrm/templates/snippets/shelf_selector.html index 663bd5633..4b32f5a8e 100644 --- a/bookwyrm/templates/snippets/shelf_selector.html +++ b/bookwyrm/templates/snippets/shelf_selector.html @@ -78,11 +78,11 @@ {% 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 %} +{% 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 %} +{% 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 %} +{% 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 %} From a5efc798f8e7a897badc301736443f5f7087affb Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Fri, 26 Nov 2021 17:30:27 +1100 Subject: [PATCH 090/217] clean up old vars --- bookwyrm/views/shelf/shelf_actions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bookwyrm/views/shelf/shelf_actions.py b/bookwyrm/views/shelf/shelf_actions.py index 3fff92a6a..5e7e6c0c9 100644 --- a/bookwyrm/views/shelf/shelf_actions.py +++ b/bookwyrm/views/shelf/shelf_actions.py @@ -1,7 +1,6 @@ """ shelf views """ from django.db import IntegrityError, transaction from django.contrib.auth.decorators import login_required -from django.http.response import HttpResponse from django.shortcuts import get_object_or_404, redirect from django.views.decorators.http import require_POST @@ -92,7 +91,7 @@ def shelve(request): @login_required @require_POST -def unshelve(request, referer=None, book_id=False): +def unshelve(request, book_id=False): """remove a book from a user's shelf""" identity = book_id if book_id else request.POST.get("book") book = get_object_or_404(models.Edition, id=identity) From 1a37903583235ff2b4d0b98767ef3e91ac3ffeb3 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Fri, 26 Nov 2021 17:39:35 +1100 Subject: [PATCH 091/217] remove unnecessary function call arg --- bookwyrm/views/reading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/reading.py b/bookwyrm/views/reading.py index a91fa8e7a..35847558e 100644 --- a/bookwyrm/views/reading.py +++ b/bookwyrm/views/reading.py @@ -101,7 +101,7 @@ class ReadingStatus(View): and current_status_shelfbook.shelf.identifier != desired_shelf.identifier ): - return unshelve(request, referer=referer, book_id=book_id) + return unshelve(request, book_id=book_id) if is_api_request(request): return HttpResponse() From 9d52e3cf273e1fa97051b23fbc4508b2fb574005 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sat, 27 Nov 2021 18:32:50 +1100 Subject: [PATCH 092/217] add ostatus subscribe to webfinger links --- bookwyrm/views/wellknown.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bookwyrm/views/wellknown.py b/bookwyrm/views/wellknown.py index 04aa88bf2..c9b1c1299 100644 --- a/bookwyrm/views/wellknown.py +++ b/bookwyrm/views/wellknown.py @@ -30,6 +30,10 @@ def webfinger(request): "rel": "self", "type": "application/activity+json", "href": user.remote_id, + }, + { + "rel": "http://ostatus.org/schema/1.0/subscribe", + "template": f"https://{DOMAIN}/ostatus_subscribe?acct={{uri}}" } ], } From f7c8f121b9c95f0c4ef7e68a358736f1dd209067 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 12:43:29 +1100 Subject: [PATCH 093/217] add remote follow ostatus templates --- bookwyrm/templates/ostatus/ostatus_error.html | 57 ++++++++++ .../templates/ostatus/ostatus_subscribe.html | 48 ++++++++ bookwyrm/templates/ostatus/template.html | 106 ++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 bookwyrm/templates/ostatus/ostatus_error.html create mode 100644 bookwyrm/templates/ostatus/ostatus_subscribe.html create mode 100644 bookwyrm/templates/ostatus/template.html diff --git a/bookwyrm/templates/ostatus/ostatus_error.html b/bookwyrm/templates/ostatus/ostatus_error.html new file mode 100644 index 000000000..5fbc8e945 --- /dev/null +++ b/bookwyrm/templates/ostatus/ostatus_error.html @@ -0,0 +1,57 @@ +{% extends 'ostatus/template.html' %} +{% load i18n %} +{% load utilities %} +{% load markdown %} + +{% block title %} +{% if not request.user.is_authenticated %} +{% trans "Log in to " %} +{% else %} +{% trans "Error following from " %} +{% endif %} +{% endblock %} + +{% block heading %} +{% if not request.user.is_authenticated %} +Let's log in first... +{% else %} +Uh oh... +{% endif %} +{% endblock %} + +{% block content %} +
    + {% if not request.user.is_authenticated %} + + {% elif error == 'ostatus_subscribe' %} +
    +

    {% blocktrans %}Something went wrong trying to follow {{ account }}{% endblocktrans %}

    +

    {% trans 'Check you have the correct username before trying again.' %}

    +
    + {% endif %} +
    +{% endblock %} diff --git a/bookwyrm/templates/ostatus/ostatus_subscribe.html b/bookwyrm/templates/ostatus/ostatus_subscribe.html new file mode 100644 index 000000000..7e929202e --- /dev/null +++ b/bookwyrm/templates/ostatus/ostatus_subscribe.html @@ -0,0 +1,48 @@ +{% extends 'ostatus/template.html' %} +{% load i18n %} +{% load utilities %} +{% load markdown %} + +{% if error or not request.user.is_authenticated %} + {% include 'ostatus/ostatus_error.html' %} +{% else %} + +{% block title %}{% trans "Follow from " %}{% endblock %} + +{% block heading %}Follow from {{ site.name }}{% endblock %} + +{% block content %} +
    +
    + +
    + {% if user.summary %} + {{ user.summary|to_markdown|safe|truncatechars_html:120 }} + {% else %} {% endif %} +
    +
    +
    +{% endblock %} + +{% endif %} diff --git a/bookwyrm/templates/ostatus/template.html b/bookwyrm/templates/ostatus/template.html new file mode 100644 index 000000000..2e8ee7b3c --- /dev/null +++ b/bookwyrm/templates/ostatus/template.html @@ -0,0 +1,106 @@ +{% load layout %} +{% load i18n %} +{% load static %} +{% load utilities %} +{% load markdown %} + + + + + {% block title %}{% endblock %}{{ site.name }} + + + + + + + + + + {% if preview_images_enabled is True %} + + {% else %} + + {% endif %} + + + + + + {% block opengraph_images %} + {% include 'snippets/opengraph_images.html' %} + {% endblock %} + + + + + + + +
    +
    + {% block content%}{% endblock %} +
    +
    + + + + + + + + + + + +{% block scripts %}{% endblock %} + + From d05e100421eaf53946e6cd420b2d32f45b35ab2f Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 13:28:58 +1100 Subject: [PATCH 094/217] update ostatus templates --- bookwyrm/templates/ostatus/ostatus_error.html | 19 ------------- .../templates/ostatus/ostatus_subscribe.html | 28 ++++++++++++++----- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/bookwyrm/templates/ostatus/ostatus_error.html b/bookwyrm/templates/ostatus/ostatus_error.html index 5fbc8e945..de2ba988b 100644 --- a/bookwyrm/templates/ostatus/ostatus_error.html +++ b/bookwyrm/templates/ostatus/ostatus_error.html @@ -1,23 +1,4 @@ -{% extends 'ostatus/template.html' %} {% load i18n %} -{% load utilities %} -{% load markdown %} - -{% block title %} -{% if not request.user.is_authenticated %} -{% trans "Log in to " %} -{% else %} -{% trans "Error following from " %} -{% endif %} -{% endblock %} - -{% block heading %} -{% if not request.user.is_authenticated %} -Let's log in first... -{% else %} -Uh oh... -{% endif %} -{% endblock %} {% block content %}
    diff --git a/bookwyrm/templates/ostatus/ostatus_subscribe.html b/bookwyrm/templates/ostatus/ostatus_subscribe.html index 7e929202e..9d87d8ef8 100644 --- a/bookwyrm/templates/ostatus/ostatus_subscribe.html +++ b/bookwyrm/templates/ostatus/ostatus_subscribe.html @@ -3,15 +3,30 @@ {% load utilities %} {% load markdown %} -{% if error or not request.user.is_authenticated %} - {% include 'ostatus/ostatus_error.html' %} +{% block title %} +{% if not request.user.is_authenticated %} +{% trans "Log in to " %} +{% elif error %} +{% trans "Error following from " %} {% else %} +{% trans "Follow from " %} +{% endif %} +{% endblock %} -{% block title %}{% trans "Follow from " %}{% endblock %} - -{% block heading %}Follow from {{ site.name }}{% endblock %} +{% block heading %} +{% if not request.user.is_authenticated %} +{% trans "Let's log in first..." %} +{% elif error %} +{% trans 'Uh oh...' %} +{% else %} +{% blocktrans %}Follow from {{ site.name }}{% endblocktrans %} +{% endif %} +{% endblock %} {% block content %} +{% if error or not request.user.is_authenticated %} + {% include 'ostatus/ostatus_error.html' with error=error user=user account=account %} +{% else %}
    @@ -43,6 +58,5 @@
    -{% endblock %} - {% endif %} +{% endblock %} From 610114b4ebfcd27cde9f76244d559c226e4d78b5 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 16:54:25 +1100 Subject: [PATCH 095/217] rearrange ostatus templates --- .../{ostatus_error.html => error.html} | 14 +++++++- ...{ostatus_subscribe.html => subscribe.html} | 7 ++-- bookwyrm/templates/ostatus/success.html | 32 +++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) rename bookwyrm/templates/ostatus/{ostatus_error.html => error.html} (71%) rename bookwyrm/templates/ostatus/{ostatus_subscribe.html => subscribe.html} (86%) create mode 100644 bookwyrm/templates/ostatus/success.html diff --git a/bookwyrm/templates/ostatus/ostatus_error.html b/bookwyrm/templates/ostatus/error.html similarity index 71% rename from bookwyrm/templates/ostatus/ostatus_error.html rename to bookwyrm/templates/ostatus/error.html index de2ba988b..b6e858e24 100644 --- a/bookwyrm/templates/ostatus/ostatus_error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -29,10 +29,22 @@
    {% elif error == 'ostatus_subscribe' %} -
    +

    {% blocktrans %}Something went wrong trying to follow {{ account }}{% endblocktrans %}

    {% trans 'Check you have the correct username before trying again.' %}

    + {% elif error == 'is_blocked' %} +
    +

    {% blocktrans %}You have blocked {{ account }}{% endblocktrans %}

    +
    + {% elif error == 'already_following' %} +
    +

    {% blocktrans %}You are already following {{ account }}{% endblocktrans %}

    +
    + {% elif error == 'already_requested' %} +
    +

    {% blocktrans %}You have already requested to follow {{ account }}{% endblocktrans %}

    +
    {% endif %}
    {% endblock %} diff --git a/bookwyrm/templates/ostatus/ostatus_subscribe.html b/bookwyrm/templates/ostatus/subscribe.html similarity index 86% rename from bookwyrm/templates/ostatus/ostatus_subscribe.html rename to bookwyrm/templates/ostatus/subscribe.html index 9d87d8ef8..e64be6029 100644 --- a/bookwyrm/templates/ostatus/ostatus_subscribe.html +++ b/bookwyrm/templates/ostatus/subscribe.html @@ -25,7 +25,7 @@ {% block content %} {% if error or not request.user.is_authenticated %} - {% include 'ostatus/ostatus_error.html' with error=error user=user account=account %} + {% include 'ostatus/error.html' with error=error user=user account=account %} {% else %}
    @@ -45,13 +45,14 @@ @{{ user|username }} -
    + {% csrf_token %} +
    -
    +
    {% if user.summary %} {{ user.summary|to_markdown|safe|truncatechars_html:120 }} {% else %} {% endif %} diff --git a/bookwyrm/templates/ostatus/success.html b/bookwyrm/templates/ostatus/success.html new file mode 100644 index 000000000..10b4409f3 --- /dev/null +++ b/bookwyrm/templates/ostatus/success.html @@ -0,0 +1,32 @@ +{% extends 'ostatus/template.html' %} +{% load i18n %} +{% load utilities %} + +{% block content %} + +{% endblock %} From e275b98183cdaed4e33d3e11e51307aa63187def Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 16:56:21 +1100 Subject: [PATCH 096/217] ostatus remote follow views --- bookwyrm/urls.py | 3 ++ bookwyrm/views/__init__.py | 2 +- bookwyrm/views/follow.py | 82 +++++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 514bb7e60..79e6e2a98 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -44,6 +44,7 @@ urlpatterns = [ re_path(r"^api/v1/instance/?$", views.instance_info), re_path(r"^api/v1/instance/peers/?$", views.peers), re_path(r"^opensearch.xml$", views.opensearch, name="opensearch"), + re_path(r"^ostatus_subscribe/?$", views.ostatus_follow_request), # polling updates re_path("^api/updates/notifications/?$", views.get_notification_count), re_path("^api/updates/stream/(?P[a-z]+)/?$", views.get_unread_status_count), @@ -450,4 +451,6 @@ urlpatterns = [ re_path(r"^unfollow/?$", views.unfollow, name="unfollow"), re_path(r"^accept-follow-request/?$", views.accept_follow_request), re_path(r"^delete-follow-request/?$", views.delete_follow_request), + # re_path(r"^ostatus_follow/?$", views.remote_follow), + re_path(r"^ostatus_success/?$", views.ostatus_follow_success, name="ostatus-success"), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index d79de4248..034b1830a 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -58,7 +58,7 @@ from .author import Author, EditAuthor from .directory import Directory from .discover import Discover from .feed import DirectMessage, Feed, Replies, Status -from .follow import follow, unfollow +from .follow import follow, unfollow, ostatus_follow_request, ostatus_follow_success from .follow import accept_follow_request, delete_follow_request from .get_started import GetStartedBooks, GetStartedProfile, GetStartedUsers from .goal import Goal, hide_goal diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index 7d91ce5b4..471fe3079 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -1,11 +1,14 @@ """ views for actions you can take in the application """ +import urllib.parse +import re from django.contrib.auth.decorators import login_required from django.db import IntegrityError from django.shortcuts import get_object_or_404, redirect +from django.template.response import TemplateResponse from django.views.decorators.http import require_POST from bookwyrm import models -from .helpers import get_user_from_username +from .helpers import get_user_from_username, handle_remote_webfinger @login_required @@ -23,9 +26,13 @@ def follow(request): except IntegrityError: pass + if request.GET.get("next"): + return redirect(request.GET.get("next", "/")) + return redirect(to_follow.local_path) + @login_required @require_POST def unfollow(request): @@ -84,3 +91,76 @@ def delete_follow_request(request): follow_request.delete() return redirect(f"/user/{request.user.localname}") + +def ostatus_follow_request(request): + """prepare an outgoing remote follow request""" + + # parse the acct URI into a user string + uri = urllib.parse.unquote(request.GET.get("acct")) + username_parts = re.search("(?:^http(?:s?):\/\/)([\w\-\.]*)(?:.)*(?:(?:\/)([\w]*))", uri) + account = f"{username_parts[2]}@{username_parts[1]}" + user = handle_remote_webfinger(account) + error = None + + if user is None or user == "": + error = "ostatus_subscribe" + + if bool(user) and user in request.user.blocks.all(): + error = "is_blocked" + + if hasattr(user, "followers") and request.user in user.followers.all(): + error = "already_following" + + if hasattr(user, "follower_requests") and request.user in user.follower_requests.all(): + error = "already_requested" + + data = { + "account": account, + "user": user, + "error": error + } + + return TemplateResponse(request, "ostatus/subscribe.html", data) + + +@login_required +def ostatus_follow_success(request): + """display success message for remote follow""" + user = get_user_from_username(request.user, request.GET.get("following")) + data = { + "account": user.name, + "user": user, + "error": None + } + return TemplateResponse(request, "ostatus/success.html", data) + +@login_required +@require_POST +def remote_follow(request): + """complete an incoming remote follow request""" + + # this is triggered from remote follow form + # attempt the follow request + # on success [[return success page]] + # on fail return [[ostatus_error]] + + +""" +REQUEST TO FOLLOW FROM REMOTE ACCOUNT +1. click remote follow button [default checked option to open new window] +2. popup new small window +3. enter user acct to follow from (user@domain.tld) and submit form +5. GET {base_url}/.well-known/webfinger/?resource=acct:{user@domain.tld} +6. parse json for links +6.1 rel="http://ostatus.org/schema/1.0/subscribe" and return 'template' +6.2 rel="self" and return href +7. replace '{uri}' in the returned string with self.href +8. GET the URI at 6.1 + +REQUEST TO FOLLOW FROM LOCAL ACCOUNT +1. receive request to /ostatus_subscribe?acct={uri} +2. check user is logged in and present confirmation screen (remote_follow_request) +3. On confirmation, 3. parse user into info needed for a normal follow +4. send follow request, on 200 response display success else display error (remote_follow) +5. Include button inviting to close window +""" From 2e428e6ea1687c15c87856f682a572cdff098e9c Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 20:08:54 +1100 Subject: [PATCH 097/217] add remote follow templates --- bookwyrm/templates/ostatus/remote_follow.html | 43 +++++++++++++++++++ .../ostatus/remote_follow_button.html | 16 +++++++ 2 files changed, 59 insertions(+) create mode 100644 bookwyrm/templates/ostatus/remote_follow.html create mode 100644 bookwyrm/templates/ostatus/remote_follow_button.html diff --git a/bookwyrm/templates/ostatus/remote_follow.html b/bookwyrm/templates/ostatus/remote_follow.html new file mode 100644 index 000000000..ea8881e42 --- /dev/null +++ b/bookwyrm/templates/ostatus/remote_follow.html @@ -0,0 +1,43 @@ +{% extends 'ostatus/template.html' %} +{% load i18n %} +{% load utilities %} + +{% block content %} +
    +
    +

    {% blocktrans %}Follow {{ user.display_name }} on the fediverse{% endblocktrans %}

    +
    + +
    +
    +
    +
    + {% csrf_token %} + + + +
    +
    +
    +
    +{% endblock %} diff --git a/bookwyrm/templates/ostatus/remote_follow_button.html b/bookwyrm/templates/ostatus/remote_follow_button.html new file mode 100644 index 000000000..4789d3064 --- /dev/null +++ b/bookwyrm/templates/ostatus/remote_follow_button.html @@ -0,0 +1,16 @@ +{% load i18n %} +{% if request.user == user %} +{% else %} + +
    +
    +
    + {% csrf_token %} + + +
    +
    +
    +{% endif %} From 6e7d23c1aec60317e7989aaf5cafa08112d49cc0 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 20:09:29 +1100 Subject: [PATCH 098/217] add remote follow button --- bookwyrm/templates/user/layout.html | 3 +++ bookwyrm/urls.py | 3 ++- bookwyrm/views/__init__.py | 2 +- bookwyrm/views/follow.py | 34 +++++++++++++++-------------- bookwyrm/views/helpers.py | 27 +++++++++++++++++++++++ 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/bookwyrm/templates/user/layout.html b/bookwyrm/templates/user/layout.html index d7557ae7b..03e3dfce8 100755 --- a/bookwyrm/templates/user/layout.html +++ b/bookwyrm/templates/user/layout.html @@ -39,6 +39,9 @@ {% if not is_self and request.user.is_authenticated %} {% include 'snippets/follow_button.html' with user=user %} {% endif %} + {% if not is_self %} + {% include 'ostatus/remote_follow_button.html' with user=user %} + {% endif %} {% if is_self and user.follower_requests.all %}
    diff --git a/bookwyrm/templates/ostatus/template.html b/bookwyrm/templates/ostatus/template.html index 2e8ee7b3c..cb922f9bd 100644 --- a/bookwyrm/templates/ostatus/template.html +++ b/bookwyrm/templates/ostatus/template.html @@ -92,7 +92,6 @@
    - diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 48fe0f6cc..45837ec13 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -453,5 +453,7 @@ urlpatterns = [ re_path(r"^delete-follow-request/?$", views.delete_follow_request), re_path(r"^ostatus_follow/?$", views.remote_follow, name="remote-follow"), re_path(r"^remote_follow/?$", views.remote_follow_page, name="remote-follow-page"), - re_path(r"^ostatus_success/?$", views.ostatus_follow_success, name="ostatus-success"), + re_path( + r"^ostatus_success/?$", views.ostatus_follow_success, name="ostatus-success" + ), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 3b5bf8232..4a92578c2 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -58,7 +58,14 @@ from .author import Author, EditAuthor from .directory import Directory from .discover import Discover from .feed import DirectMessage, Feed, Replies, Status -from .follow import follow, unfollow, ostatus_follow_request, ostatus_follow_success, remote_follow, remote_follow_page +from .follow import ( + follow, + unfollow, + ostatus_follow_request, + ostatus_follow_success, + remote_follow, + remote_follow_page, +) from .follow import accept_follow_request, delete_follow_request from .get_started import GetStartedBooks, GetStartedProfile, GetStartedUsers from .goal import Goal, hide_goal diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index 2ebe0ce04..58d979854 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -8,7 +8,11 @@ from django.template.response import TemplateResponse from django.views.decorators.http import require_POST from bookwyrm import models -from .helpers import get_user_from_username, handle_remote_webfinger, subscribe_remote_webfinger +from .helpers import ( + get_user_from_username, + handle_remote_webfinger, + subscribe_remote_webfinger, +) @login_required @@ -32,7 +36,6 @@ def follow(request): return redirect(to_follow.local_path) - @login_required @require_POST def unfollow(request): @@ -92,12 +95,15 @@ def delete_follow_request(request): follow_request.delete() return redirect(f"/user/{request.user.localname}") + def ostatus_follow_request(request): """prepare an outgoing remote follow request""" # parse the acct URI into a user string uri = urllib.parse.unquote(request.GET.get("acct")) - username_parts = re.search("(?:^http(?:s?):\/\/)([\w\-\.]*)(?:.)*(?:(?:\/)([\w]*))", uri) + username_parts = re.search( + "(?:^http(?:s?):\/\/)([\w\-\.]*)(?:.)*(?:(?:\/)([\w]*))", uri + ) account = f"{username_parts[2]}@{username_parts[1]}" user = handle_remote_webfinger(account) error = None @@ -111,14 +117,13 @@ def ostatus_follow_request(request): if hasattr(user, "followers") and request.user in user.followers.all(): error = "already_following" - if hasattr(user, "follower_requests") and request.user in user.follower_requests.all(): + if ( + hasattr(user, "follower_requests") + and request.user in user.follower_requests.all() + ): error = "already_requested" - data = { - "account": account, - "user": user, - "error": error - } + data = {"account": account, "user": user, "error": error} return TemplateResponse(request, "ostatus/subscribe.html", data) @@ -127,21 +132,17 @@ def ostatus_follow_request(request): def ostatus_follow_success(request): """display success message for remote follow""" user = get_user_from_username(request.user, request.GET.get("following")) - data = { - "account": user.name, - "user": user, - "error": None - } + data = {"account": user.name, "user": user, "error": None} return TemplateResponse(request, "ostatus/success.html", data) + def remote_follow_page(request): """Display remote follow page""" user = get_user_from_username(request.user, request.GET.get("user")) - data = { - "user": user - } + data = {"user": user} return TemplateResponse(request, "ostatus/remote_follow.html", data) + @require_POST def remote_follow(request): """direct user to follow from remote account using ostatus subscribe protocol""" diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index 607181489..650087ec0 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -84,6 +84,7 @@ def handle_remote_webfinger(query): return None return user + def subscribe_remote_webfinger(query): """get subscribe template from other servers""" template = None @@ -112,6 +113,7 @@ def subscribe_remote_webfinger(query): return template + def get_edition(book_id): """look up a book in the db and return an edition""" book = models.Book.objects.select_subclasses().get(id=book_id) diff --git a/bookwyrm/views/wellknown.py b/bookwyrm/views/wellknown.py index c9b1c1299..03e619dfd 100644 --- a/bookwyrm/views/wellknown.py +++ b/bookwyrm/views/wellknown.py @@ -32,9 +32,9 @@ def webfinger(request): "href": user.remote_id, }, { - "rel": "http://ostatus.org/schema/1.0/subscribe", - "template": f"https://{DOMAIN}/ostatus_subscribe?acct={{uri}}" - } + "rel": "http://ostatus.org/schema/1.0/subscribe", + "template": f"https://{DOMAIN}/ostatus_subscribe?acct={{uri}}", + }, ], } ) From 6abf5d69107c4440e1809e34458e169e823d7e92 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sun, 28 Nov 2021 21:48:03 +1100 Subject: [PATCH 101/217] add submit button to remote follow form --- bookwyrm/templates/ostatus/remote_follow.html | 1 + 1 file changed, 1 insertion(+) diff --git a/bookwyrm/templates/ostatus/remote_follow.html b/bookwyrm/templates/ostatus/remote_follow.html index ea8881e42..3ff769432 100644 --- a/bookwyrm/templates/ostatus/remote_follow.html +++ b/bookwyrm/templates/ostatus/remote_follow.html @@ -36,6 +36,7 @@ +
    From 54cef421e291295cac79062ceec53e145b6e397e Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 28 Nov 2021 07:57:27 -0800 Subject: [PATCH 102/217] Fixes checking if image fields are already set --- bookwyrm/models/fields.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 361079906..a28ad0ea2 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -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) From 7b89014e7baa35cf600559f18cf1588b77d8c44d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 28 Nov 2021 08:24:00 -0800 Subject: [PATCH 103/217] Updates image fields tests --- bookwyrm/tests/models/test_fields.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index 74f4c48bd..6499e96cb 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -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,10 +436,22 @@ 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") From a7ee8fea247935556a1f21705c1bc485d9cf4682 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 28 Nov 2021 08:49:54 -0800 Subject: [PATCH 104/217] Adds test for setting model image field --- bookwyrm/tests/models/test_fields.py | 29 +++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index 6499e96cb..278272d87 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -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 @@ -458,6 +458,33 @@ class ModelFields(TestCase): 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) + def test_datetime_field(self, *_): """this one is pretty simple, it just has to use isoformat""" instance = fields.DateTimeField() From 3a7f070a798760301cc6c50f6e48338e29094bf7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 28 Nov 2021 08:50:29 -0800 Subject: [PATCH 105/217] Typo fix --- bookwyrm/models/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index a28ad0ea2..7d14f88f9 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -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 From 3f09b4bc8a44db937c2cfbe02f53b78010fba801 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 28 Nov 2021 09:23:13 -0800 Subject: [PATCH 106/217] More tests --- bookwyrm/tests/models/test_fields.py | 100 +++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index 278272d87..8028a305e 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -485,6 +485,106 @@ class ModelFields(TestCase): 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() From feaf0d5e52ec8d2887b2d14e3bcd3bfc49446cf4 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 07:11:57 +1100 Subject: [PATCH 107/217] handle username errors in remote follow form --- bookwyrm/templates/ostatus/error.html | 5 +++++ bookwyrm/views/follow.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/bookwyrm/templates/ostatus/error.html b/bookwyrm/templates/ostatus/error.html index b6e858e24..cb1aec408 100644 --- a/bookwyrm/templates/ostatus/error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -33,6 +33,11 @@

    {% blocktrans %}Something went wrong trying to follow {{ account }}{% endblocktrans %}

    {% trans 'Check you have the correct username before trying again.' %}

    + {% elif error == 'remote_subscribe' %} +
    +

    {% blocktrans %}Something went wrong trying to follow from {{ account }}{% endblocktrans %}

    +

    {% trans 'Check you have the correct username before trying again.' %}

    +
    {% elif error == 'is_blocked' %}

    {% blocktrans %}You have blocked {{ account }}{% endblocktrans %}

    diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index 58d979854..fcab5d6ac 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -148,5 +148,8 @@ def remote_follow(request): """direct user to follow from remote account using ostatus subscribe protocol""" remote_user = request.POST.get("remote_user") template = subscribe_remote_webfinger(remote_user) + if template is None: + data = {"account": remote_user, "user": None, "error": "remote_subscribe"} + return TemplateResponse(request, "ostatus/subscribe.html", data) url = template.replace("{uri}", request.POST.get("user")) return redirect(url) From 403e282d888da9ad02a1a5e6da88c190d9f48994 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 21:52:28 +0100 Subject: [PATCH 108/217] Add `aria-describedby` to field help/error messages --- bookwyrm/forms.py | 43 +++++++++++++++++++ .../templates/preferences/delete_user.html | 4 +- bookwyrm/templates/preferences/edit_user.html | 22 ++++++---- bookwyrm/templates/settings/site.html | 8 ++-- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 847ca05c0..aed5a7945 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -9,6 +9,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from bookwyrm import models +from bookwyrm.models.fields import ClearableFileInputWithWarning class CustomForm(ModelForm): @@ -147,6 +148,23 @@ class EditUserForm(CustomForm): "preferred_language", ] help_texts = {f: None for f in fields} + widgets = { + "avatar": ClearableFileInputWithWarning( + attrs={'aria-describedby': "desc_avatar"} + ), + "name": forms.TextInput( + attrs={'aria-describedby': "desc_name"} + ), + "summary": forms.Textarea( + attrs={'aria-describedby': "desc_summary"} + ), + "email": forms.EmailInput( + attrs={'aria-describedby': "desc_email"} + ), + "discoverable": forms.CheckboxInput( + attrs={'aria-describedby': "desc_discoverable"} + ), + } class LimitedEditUserForm(CustomForm): @@ -160,6 +178,20 @@ class LimitedEditUserForm(CustomForm): "discoverable", ] help_texts = {f: None for f in fields} + widgets = { + "avatar": ClearableFileInputWithWarning( + attrs={'aria-describedby': "desc_avatar"} + ), + "name": forms.TextInput( + attrs={'aria-describedby': "desc_name"} + ), + "summary": forms.Textarea( + attrs={'aria-describedby': "desc_summary"} + ), + "discoverable": forms.CheckboxInput( + attrs={'aria-describedby': "desc_discoverable"} + ), + } class DeleteUserForm(CustomForm): @@ -288,6 +320,17 @@ class SiteForm(CustomForm): class Meta: model = models.SiteSettings exclude = [] + widgets = { + "instance_short_description": forms.TextInput( + attrs={'aria-describedby': "desc_instance_short_description"} + ), + "require_confirm_email": forms.CheckboxInput( + attrs={'aria-describedby': "desc_require_confirm_email"} + ), + "invite_request_text": forms.Textarea( + attrs={'aria-describedby': "desc_invite_request_text"} + ), + } class AnnouncementForm(CustomForm): diff --git a/bookwyrm/templates/preferences/delete_user.html b/bookwyrm/templates/preferences/delete_user.html index 63bd2f860..a72cc97d7 100644 --- a/bookwyrm/templates/preferences/delete_user.html +++ b/bookwyrm/templates/preferences/delete_user.html @@ -18,9 +18,9 @@ {% csrf_token %}
    - + {% for error in form.password.errors %} -

    {{ error | escape }}

    +

    {{ error | escape }}

    {% endfor %}
    diff --git a/bookwyrm/templates/preferences/edit_user.html b/bookwyrm/templates/preferences/edit_user.html index 72c49dbe5..a3f8962c8 100644 --- a/bookwyrm/templates/preferences/edit_user.html +++ b/bookwyrm/templates/preferences/edit_user.html @@ -34,7 +34,7 @@
    {{ form.avatar }} {% for error in form.avatar.errors %} -

    {{ error | escape }}

    +

    {{ error | escape }}

    {% endfor %}
    @@ -42,21 +42,21 @@ {{ form.name }} {% for error in form.name.errors %} -

    {{ error | escape }}

    +

    {{ error | escape }}

    {% endfor %}
    {{ form.summary }} {% for error in form.summary.errors %} -

    {{ error | escape }}

    +

    {{ error | escape }}

    {% endfor %}
    {{ form.email }} {% for error in form.email.errors %} -

    {{ error | escape }}

    +

    {{ error | escape }}

    {% endfor %}
    @@ -69,19 +69,23 @@
    +
    +
    +
    +
    {% url 'directory' as path %} -

    +

    {% blocktrans %}Your account will show up in the directory, and may be recommended to other BookWyrm users.{% endblocktrans %}

    @@ -107,8 +111,8 @@
    diff --git a/bookwyrm/templates/settings/site.html b/bookwyrm/templates/settings/site.html index 94a4dd454..01b25036b 100644 --- a/bookwyrm/templates/settings/site.html +++ b/bookwyrm/templates/settings/site.html @@ -33,8 +33,8 @@ {{ site_form.instance_description }}
    - -

    {% trans "Used when the instance is previewed on joinbookwyrm.com. Does not support HTML or Markdown." %}

    + +

    {% trans "Used when the instance is previewed on joinbookwyrm.com. Does not support HTML or Markdown." %}

    {{ site_form.instance_short_description }}
    @@ -114,7 +114,7 @@ {{ site_form.require_confirm_email }} {% trans "Require users to confirm email address" %} -

    {% trans "(Recommended if registration is open)" %}

    +

    {% trans "(Recommended if registration is open)" %}

    @@ -124,7 +124,7 @@ {{ site_form.invite_request_text }} {% for error in site_form.invite_request_text.errors %} -

    {{ error|escape }}

    +

    {{ error|escape }}

    {% endfor %}
    From 46f32944315b9add4f04776668bbf7c2117efc12 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 07:56:09 +1100 Subject: [PATCH 109/217] fix remote follow template --- bookwyrm/templates/ostatus/remote_follow.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/ostatus/remote_follow.html b/bookwyrm/templates/ostatus/remote_follow.html index 3ff769432..98442547e 100644 --- a/bookwyrm/templates/ostatus/remote_follow.html +++ b/bookwyrm/templates/ostatus/remote_follow.html @@ -24,7 +24,7 @@ @{{ user|username }} -

    Follow {{ user.name }} from another Fediverse account like Bookwyrm, Mastodon, or Pleroma.

    +

    Follow {{ user.display_name }} from another Fediverse account like Bookwyrm, Mastodon, or Pleroma.

    From c7242b6022c9e70725e9445255fe766ecedee2ed Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 07:56:31 +1100 Subject: [PATCH 110/217] add popup warning --- bookwyrm/templates/ostatus/remote_follow_button.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/ostatus/remote_follow_button.html b/bookwyrm/templates/ostatus/remote_follow_button.html index 2848fde0e..fc869229a 100644 --- a/bookwyrm/templates/ostatus/remote_follow_button.html +++ b/bookwyrm/templates/ostatus/remote_follow_button.html @@ -4,9 +4,12 @@ {% endif %} From 85c688b1475bf79649f49619d8ab56a3200cd9b7 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sun, 28 Nov 2021 22:01:49 +0100 Subject: [PATCH 111/217] Update forms.py --- bookwyrm/forms.py | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index aed5a7945..ffbb237b8 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -150,19 +150,13 @@ class EditUserForm(CustomForm): help_texts = {f: None for f in fields} widgets = { "avatar": ClearableFileInputWithWarning( - attrs={'aria-describedby': "desc_avatar"} - ), - "name": forms.TextInput( - attrs={'aria-describedby': "desc_name"} - ), - "summary": forms.Textarea( - attrs={'aria-describedby': "desc_summary"} - ), - "email": forms.EmailInput( - attrs={'aria-describedby': "desc_email"} + attrs={"aria-describedby": "desc_avatar"} ), + "name": forms.TextInput(attrs={"aria-describedby": "desc_name"}), + "summary": forms.Textarea(attrs={"aria-describedby": "desc_summary"}), + "email": forms.EmailInput(attrs={"aria-describedby": "desc_email"}), "discoverable": forms.CheckboxInput( - attrs={'aria-describedby': "desc_discoverable"} + attrs={"aria-describedby": "desc_discoverable"} ), } @@ -180,16 +174,12 @@ class LimitedEditUserForm(CustomForm): help_texts = {f: None for f in fields} widgets = { "avatar": ClearableFileInputWithWarning( - attrs={'aria-describedby': "desc_avatar"} - ), - "name": forms.TextInput( - attrs={'aria-describedby': "desc_name"} - ), - "summary": forms.Textarea( - attrs={'aria-describedby': "desc_summary"} + attrs={"aria-describedby": "desc_avatar"} ), + "name": forms.TextInput(attrs={"aria-describedby": "desc_name"}), + "summary": forms.Textarea(attrs={"aria-describedby": "desc_summary"}), "discoverable": forms.CheckboxInput( - attrs={'aria-describedby': "desc_discoverable"} + attrs={"aria-describedby": "desc_discoverable"} ), } @@ -322,13 +312,13 @@ class SiteForm(CustomForm): exclude = [] widgets = { "instance_short_description": forms.TextInput( - attrs={'aria-describedby': "desc_instance_short_description"} + attrs={"aria-describedby": "desc_instance_short_description"} ), "require_confirm_email": forms.CheckboxInput( - attrs={'aria-describedby': "desc_require_confirm_email"} + attrs={"aria-describedby": "desc_require_confirm_email"} ), "invite_request_text": forms.Textarea( - attrs={'aria-describedby': "desc_invite_request_text"} + attrs={"aria-describedby": "desc_invite_request_text"} ), } From 4a9713b812d65d2bc2f9ef4ecbc1eeec8f6a617f Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 08:03:01 +1100 Subject: [PATCH 112/217] fix template for remote follower error --- bookwyrm/templates/ostatus/error.html | 2 +- bookwyrm/templates/ostatus/subscribe.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/ostatus/error.html b/bookwyrm/templates/ostatus/error.html index cb1aec408..442c35b9e 100644 --- a/bookwyrm/templates/ostatus/error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -2,7 +2,7 @@ {% block content %}
    - {% if not request.user.is_authenticated %} + {% if not request.user.is_authenticated and not error == 'remote_subscribe' %}
    diff --git a/bookwyrm/templates/ostatus/success.html b/bookwyrm/templates/ostatus/success.html index 10b4409f3..d8c311829 100644 --- a/bookwyrm/templates/ostatus/success.html +++ b/bookwyrm/templates/ostatus/success.html @@ -22,11 +22,14 @@ @{{ user|username }} - - - {% include 'snippets/avatar.html' with user=user large=True %} - +

    + + {% trans 'You are now following ' %}{{ user.display_name }}! +

    + {% endblock %} From 3d73ea92e85b84bfc4f7e2fc5a8fab5179767e00 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 18:08:25 +1100 Subject: [PATCH 115/217] handle user blocks properly --- bookwyrm/templates/ostatus/error.html | 4 +++ bookwyrm/views/follow.py | 36 +++++++++++++++++++-------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/bookwyrm/templates/ostatus/error.html b/bookwyrm/templates/ostatus/error.html index 91bb6a0a4..8a047172f 100644 --- a/bookwyrm/templates/ostatus/error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -42,6 +42,10 @@

    {% blocktrans %}You have blocked {{ account }}{% endblocktrans %}

    + {% elif error == 'has_blocked' %} +
    +

    {% blocktrans %}{{ account }} has blocked you{% endblocktrans %}

    +
    {% elif error == 'already_following' %}

    {% blocktrans %}You are already following {{ account }}{% endblocktrans %}

    diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index 1555fc5e4..83b900354 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -109,17 +109,33 @@ def ostatus_follow_request(request): if user is None or user == "": error = "ostatus_subscribe" - if hasattr(request.user, "blocks") and user in request.user.blocks.all(): - error = "is_blocked" + # don't do these checks for AnonymousUser before they sign in + if request.user.id: - if hasattr(user, "followers") and request.user in user.followers.all(): - error = "already_following" - - if ( - hasattr(user, "follower_requests") - and request.user in user.follower_requests.all() - ): - error = "already_requested" + # you have blocked them so you probably don't want to follow + if ( + hasattr(request.user, "blocks") + and user in request.user.blocks.all() + ): + error = "is_blocked" + # they have blocked you + if ( + hasattr(user, "blocks") + and request.user in user.blocks.all() + ): + error = "has_blocked" + # you're already following them + if ( + hasattr(user, "followers") + and request.user in user.followers.all() + ): + error = "already_following" + # you're not following yet but you already asked + if ( + hasattr(user, "follower_requests") + and request.user in user.follower_requests.all() + ): + error = "already_requested" data = {"account": account, "user": user, "error": error} From f5d9a204ebfd0045a04046200feaeaa3b21d68d8 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 19:37:56 +1100 Subject: [PATCH 116/217] clean up ostatus templates --- bookwyrm/templates/ostatus/error.html | 46 +++--- bookwyrm/templates/ostatus/remote_follow.html | 67 +++++---- bookwyrm/templates/ostatus/success.html | 46 +++--- bookwyrm/templates/ostatus/template.html | 133 +++++++++--------- 4 files changed, 145 insertions(+), 147 deletions(-) diff --git a/bookwyrm/templates/ostatus/error.html b/bookwyrm/templates/ostatus/error.html index 8a047172f..085fa3454 100644 --- a/bookwyrm/templates/ostatus/error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -4,30 +4,28 @@
    {% if not request.user.is_authenticated and not error == 'remote_subscribe' %} +
    +
    +
    + {% csrf_token %} +
    +
    + + +
    +
    + + +

    {% trans "Forgot your password?" %}

    +
    +
    + +
    +
    +
    +
    +
    +
    {% elif error == 'ostatus_subscribe' %}

    {% blocktrans %}Something went wrong trying to follow {{ account }}{% endblocktrans %}

    diff --git a/bookwyrm/templates/ostatus/remote_follow.html b/bookwyrm/templates/ostatus/remote_follow.html index ef8f1b90f..6a4e565ac 100644 --- a/bookwyrm/templates/ostatus/remote_follow.html +++ b/bookwyrm/templates/ostatus/remote_follow.html @@ -4,41 +4,40 @@ {% block content %}
    -
    -

    {% blocktrans %}Follow {{ user.display_name }} on the fediverse{% endblocktrans %}

    -
    -
    -
    - - {% include 'snippets/avatar.html' with user=user large=True %} - -
    - - - {{ user.display_name }} - {% if user.manually_approves_followers %} - - {% trans "Locked account" %} - - {% endif %} - - @{{ user|username }} - -

    {% blocktrans %}Follow {{ user.display_name }} from another Fediverse account like Bookwyrm, Mastodon, or Pleroma.{% endblocktrans %}

    -
    -
    +
    +

    {% blocktrans %}Follow {{ user.display_name }} on the fediverse{% endblocktrans %}

    +
    +
    +
    + + {% include 'snippets/avatar.html' with user=user large=True %} + +
    + + + {{ user.display_name }} + {% if user.manually_approves_followers %} + + {% trans "Locked account" %} + + {% endif %} + + @{{ user|username }} + +

    {% blocktrans %}Follow {{ user.display_name }} from another Fediverse account like Bookwyrm, Mastodon, or Pleroma.{% endblocktrans %}

    +
    +
    -
    -
    -
    - {% csrf_token %} - - - - -
    -
    -
    +
    +
    +
    + {% csrf_token %} + + + + +
    +
    {% endblock %} diff --git a/bookwyrm/templates/ostatus/success.html b/bookwyrm/templates/ostatus/success.html index d8c311829..89f662735 100644 --- a/bookwyrm/templates/ostatus/success.html +++ b/bookwyrm/templates/ostatus/success.html @@ -4,29 +4,29 @@ {% block content %}
    -
    diff --git a/bookwyrm/templates/ostatus/template.html b/bookwyrm/templates/ostatus/template.html index cb922f9bd..1dbb32a36 100644 --- a/bookwyrm/templates/ostatus/template.html +++ b/bookwyrm/templates/ostatus/template.html @@ -7,45 +7,46 @@ - {% block title %}{% endblock %}{{ site.name }} - - - - + {% block title %}{% endblock %}{{ site.name }} + + + + - + - + - {% if preview_images_enabled is True %} - - {% else %} - - {% endif %} - - - - + {% if preview_images_enabled is True %} + + {% else %} + + {% endif %} + + + + - {% block opengraph_images %} - {% include 'snippets/opengraph_images.html' %} - {% endblock %} - - + {% block opengraph_images %} + {% include 'snippets/opengraph_images.html' %} + {% endblock %} + + @@ -57,43 +58,43 @@ From 9a3ec4362b85ce7920632ff6a74ee44f4b99d9ff Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 19:45:52 +1100 Subject: [PATCH 117/217] code cleanup --- bookwyrm/static/js/bookwyrm.js | 13 ++++++------- bookwyrm/views/follow.py | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 86a021af8..ebac78a91 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -376,12 +376,11 @@ let BookWyrm = new class { * @param {string} windowName windowName * @return {undefined} */ - displayPopUp(url, windowName){ - - window.open( - url, - windowName, - "left=100,top=100,width=430,height=600" - ) + displayPopUp(url, windowName) { + window.open( + url, + windowName, + "left=100,top=100,width=430,height=600" + ); } }(); diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index 83b900354..11bff60a3 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -100,7 +100,7 @@ def ostatus_follow_request(request): """prepare an outgoing remote follow request""" uri = urllib.parse.unquote(request.GET.get("acct")) username_parts = re.search( - "(?:^http(?:s?):\/\/)([\w\-\.]*)(?:.)*(?:(?:\/)([\w]*))", uri + r"(?:^http(?:s?):\/\/)([\w\-\.]*)(?:.)*(?:(?:\/)([\w]*))", uri ) account = f"{username_parts[2]}@{username_parts[1]}" user = handle_remote_webfinger(account) From 1211fda7ff82a2eca793981cb5fbddda4643af5b Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 19:53:13 +1100 Subject: [PATCH 118/217] beautiful code quality, pylint will be pleased --- bookwyrm/templates/ostatus/template.html | 2 +- bookwyrm/views/follow.py | 19 ++++--------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/bookwyrm/templates/ostatus/template.html b/bookwyrm/templates/ostatus/template.html index 1dbb32a36..7d670b0a5 100644 --- a/bookwyrm/templates/ostatus/template.html +++ b/bookwyrm/templates/ostatus/template.html @@ -33,7 +33,7 @@ diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index 11bff60a3..7af8b0db7 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -113,22 +113,13 @@ def ostatus_follow_request(request): if request.user.id: # you have blocked them so you probably don't want to follow - if ( - hasattr(request.user, "blocks") - and user in request.user.blocks.all() - ): + if hasattr(request.user, "blocks") and user in request.user.blocks.all(): error = "is_blocked" # they have blocked you - if ( - hasattr(user, "blocks") - and request.user in user.blocks.all() - ): + if hasattr(user, "blocks") and request.user in user.blocks.all(): error = "has_blocked" # you're already following them - if ( - hasattr(user, "followers") - and request.user in user.followers.all() - ): + if hasattr(user, "followers") and request.user in user.followers.all(): error = "already_following" # you're not following yet but you already asked if ( @@ -165,8 +156,6 @@ def remote_follow(request): if template is None: data = {"account": remote_user, "user": None, "error": "remote_subscribe"} return TemplateResponse(request, "ostatus/subscribe.html", data) - user = get_object_or_404( - models.User, id=request.POST.get("user") - ) + user = get_object_or_404(models.User, id=request.POST.get("user")) url = template.replace("{uri}", urllib.parse.quote(user.remote_id)) return redirect(url) From 1d90ca6fa62362e840ca2ba9fd0306b0ea8a2752 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 20:35:26 +1100 Subject: [PATCH 119/217] keep footer DRY Pulls footer and scripts after it into a separate component template. This allows ostatus/template to use the footer without having to use layout without repeating the same code. --- bookwyrm/templates/components/footer.html | 49 +++++++++++++++++++++++ bookwyrm/templates/layout.html | 45 +-------------------- bookwyrm/templates/ostatus/template.html | 48 +--------------------- 3 files changed, 51 insertions(+), 91 deletions(-) create mode 100644 bookwyrm/templates/components/footer.html diff --git a/bookwyrm/templates/components/footer.html b/bookwyrm/templates/components/footer.html new file mode 100644 index 000000000..047d7bfad --- /dev/null +++ b/bookwyrm/templates/components/footer.html @@ -0,0 +1,49 @@ +{% load layout %} +{% load i18n %} +{% load static %} + + + + + + + + + +{% block scripts %}{% endblock %} diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index f2d04f961..50a7ae6d1 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -222,50 +222,7 @@
    - +{% include 'components/footer.html' %} - - - - - - -{% block scripts %}{% endblock %} diff --git a/bookwyrm/templates/ostatus/template.html b/bookwyrm/templates/ostatus/template.html index 7d670b0a5..04e432aaa 100644 --- a/bookwyrm/templates/ostatus/template.html +++ b/bookwyrm/templates/ostatus/template.html @@ -48,59 +48,13 @@
    - -
    {% block content%}{% endblock %}
    - - +{% include 'components/footer.html' %} - - - - - - -{% block scripts %}{% endblock %} From 1636dfd308ca8eb8827a6aa8f6be9587bc902656 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Mon, 29 Nov 2021 20:42:16 +1100 Subject: [PATCH 120/217] fix footer indentation --- bookwyrm/templates/components/footer.html | 68 +++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/bookwyrm/templates/components/footer.html b/bookwyrm/templates/components/footer.html index 047d7bfad..df11e9d55 100644 --- a/bookwyrm/templates/components/footer.html +++ b/bookwyrm/templates/components/footer.html @@ -3,43 +3,43 @@ {% load static %} From dd0114c64468b84323aa7cc7526baee683ca07b5 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 22:33:03 +0100 Subject: [PATCH 121/217] Include errors display snippet --- .../templates/preferences/delete_user.html | 5 ++--- bookwyrm/templates/preferences/edit_user.html | 20 ++++++++----------- bookwyrm/templates/settings/site.html | 5 ++--- bookwyrm/templates/snippets/form_errors.html | 9 +++++++++ 4 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 bookwyrm/templates/snippets/form_errors.html diff --git a/bookwyrm/templates/preferences/delete_user.html b/bookwyrm/templates/preferences/delete_user.html index a72cc97d7..b009230c5 100644 --- a/bookwyrm/templates/preferences/delete_user.html +++ b/bookwyrm/templates/preferences/delete_user.html @@ -19,9 +19,8 @@
    - {% for error in form.password.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.password.errors id="desc_password" %}
    diff --git a/bookwyrm/templates/preferences/edit_user.html b/bookwyrm/templates/preferences/edit_user.html index a3f8962c8..b18eb4e98 100644 --- a/bookwyrm/templates/preferences/edit_user.html +++ b/bookwyrm/templates/preferences/edit_user.html @@ -33,31 +33,27 @@ {% endif %}
    {{ form.avatar }} - {% for error in form.avatar.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.avatar.errors id="desc_avatar" %}
    {{ form.name }} - {% for error in form.name.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.name.errors id="desc_name" %}
    {{ form.summary }} - {% for error in form.summary.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.summary.errors id="desc_summary" %}
    {{ form.email }} - {% for error in form.email.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.email.errors id="desc_email" %}
    diff --git a/bookwyrm/templates/settings/site.html b/bookwyrm/templates/settings/site.html index 01b25036b..3c05e1473 100644 --- a/bookwyrm/templates/settings/site.html +++ b/bookwyrm/templates/settings/site.html @@ -123,9 +123,8 @@
    {{ site_form.invite_request_text }} - {% for error in site_form.invite_request_text.errors %} -

    {{ error|escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=site_form.invite_request_text.errors id="desc_invite_request_text" %}
    diff --git a/bookwyrm/templates/snippets/form_errors.html b/bookwyrm/templates/snippets/form_errors.html new file mode 100644 index 000000000..ecbf7ff8d --- /dev/null +++ b/bookwyrm/templates/snippets/form_errors.html @@ -0,0 +1,9 @@ +{% if errors_list %} +
    + {% for error in errors_list %} +

    + {{ error | escape }} +

    + {% endfor %} +
    +{% endif %} From 28f0882ba61dec1f41748d7e0ea9477ae1f71168 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 22:39:01 +0100 Subject: [PATCH 122/217] Handle Author form errors --- bookwyrm/forms.py | 34 ++++++++++++++- bookwyrm/templates/author/edit_author.html | 50 +++++++++------------- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index ffbb237b8..88820c8f1 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -236,7 +236,39 @@ class AuthorForm(CustomForm): "librarything_key", "goodreads_key", ] - + widgets = { + "name": forms.TextInput( + attrs={"aria-describedby": "desc_name"} + ), + "aliases": forms.TextInput( + attrs={"aria-describedby": "desc_aliases"} + ), + "bio": forms.Textarea( + attrs={"aria-describedby": "desc_bio"} + ), + "wikipedia_link": forms.TextInput( + attrs={"aria-describedby": "desc_wikipedia_link"} + ), + "born": forms.SelectDateWidget( + attrs={"aria-describedby": "desc_born"} + ), + "died": forms.SelectDateWidget( + attrs={"aria-describedby": "desc_died"} + ), + "oepnlibrary_key": forms.TextInput( + attrs={"aria-describedby": "desc_oepnlibrary_key"} + ), + "inventaire_id": forms.TextInput( + attrs={"aria-describedby": "desc_inventaire_id"} + ), + "librarything_key": forms.TextInput( + attrs={"aria-describedby": "desc_librarything_key"} + ), + "goodreads_key": forms.TextInput( + attrs={"aria-describedby": "desc_goodreads_key"} + ), + } + class ImportForm(forms.Form): csv_file = forms.FileField() diff --git a/bookwyrm/templates/author/edit_author.html b/bookwyrm/templates/author/edit_author.html index 54d7f4f1c..de1a7875e 100644 --- a/bookwyrm/templates/author/edit_author.html +++ b/bookwyrm/templates/author/edit_author.html @@ -34,47 +34,41 @@
    {{ form.name }} - {% for error in form.name.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.name.errors id="desc_name" %}
    {{ form.aliases }} {% trans "Separate multiple values with commas." %} - {% for error in form.aliases.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.aliases.errors id="desc_aliases" %}
    {{ form.bio }} - {% for error in form.bio.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.bio.errors id="desc_bio" %}

    {{ form.wikipedia_link }}

    - {% for error in form.wikipedia_link.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.wikipedia_link.errors id="desc_wikipedia_link" %}
    - {% for error in form.born.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.born.errors id="desc_born" %}
    - {% for error in form.died.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.died.errors id="desc_died" %}
    @@ -82,33 +76,29 @@
    {{ form.openlibrary_key }} - {% for error in form.openlibrary_key.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.oepnlibrary_key.errors id="desc_oepnlibrary_key" %}
    {{ form.inventaire_id }} - {% for error in form.inventaire_id.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.inventaire_id.errors id="desc_inventaire_id" %}
    {{ form.librarything_key }} - {% for error in form.librarything_key.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.librarything_key.errors id="desc_librarything_key" %}
    {{ form.goodreads_key }} - {% for error in form.goodreads_key.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.goodreads_key.errors id="desc_goodreads_key" %}
    From adb0d356a8d81ed63c64e74befa9a4ac9dcfea76 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 22:39:44 +0100 Subject: [PATCH 123/217] Update site.html --- bookwyrm/templates/settings/site.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/settings/site.html b/bookwyrm/templates/settings/site.html index 3c05e1473..8efad308d 100644 --- a/bookwyrm/templates/settings/site.html +++ b/bookwyrm/templates/settings/site.html @@ -124,7 +124,7 @@ {{ site_form.invite_request_text }} - {% include 'snippets/form_errors.html' with errors_list=site_form.invite_request_text.errors id="desc_invite_request_text" %} + {% include 'snippets/form_errors.html' with errors_list=site_form.invite_request_text.errors id="desc_invite_request_text" %} From c2873c601f4deb2efa05af166fe49c9a373479af Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:26:25 +0100 Subject: [PATCH 124/217] Register form --- .../templates/snippets/register_form.html | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/bookwyrm/templates/snippets/register_form.html b/bookwyrm/templates/snippets/register_form.html index 9e610bd13..a1af78eff 100644 --- a/bookwyrm/templates/snippets/register_form.html +++ b/bookwyrm/templates/snippets/register_form.html @@ -3,32 +3,31 @@
    - + + + {% include 'snippets/form_errors.html' with errors_list=register_form.localname.errors id="desc_localname_register" %}
    - {% for error in register_form.localname.errors %} -

    {{ error | escape }}

    - {% endfor %}
    - - {% for error in register_form.email.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + {% include 'snippets/form_errors.html' with errors_list=register_form.email.errors id="desc_email_register" %}
    - - {% for error in register_form.password.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + {% include 'snippets/form_errors.html' with errors_list=register_form.password.errors id="desc_password_register" %}
    - +
    From 08b4c538e621f0ba979f94aeefa89064a304d5e7 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:26:43 +0100 Subject: [PATCH 125/217] User moderation actions --- .../users/user_moderation_actions.html | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/bookwyrm/templates/settings/users/user_moderation_actions.html b/bookwyrm/templates/settings/users/user_moderation_actions.html index a976359f4..b5f69529f 100644 --- a/bookwyrm/templates/settings/users/user_moderation_actions.html +++ b/bookwyrm/templates/settings/users/user_moderation_actions.html @@ -50,18 +50,23 @@ {% endif %} {% with group=user.groups.first %}
    - {% for value, name in group_form.fields.groups.choices %} - + {% endfor %} - +
    - {% for error in group_form.groups.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=group_form.groups.errors id="desc_user_group" %} {% endwith %} - + {% endif %} From a154597de179d76f491499a06c72db430db198f1 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:26:53 +0100 Subject: [PATCH 126/217] Delete user form --- bookwyrm/templates/settings/users/delete_user_form.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templates/settings/users/delete_user_form.html b/bookwyrm/templates/settings/users/delete_user_form.html index 158745d05..1ea63269d 100644 --- a/bookwyrm/templates/settings/users/delete_user_form.html +++ b/bookwyrm/templates/settings/users/delete_user_form.html @@ -15,10 +15,9 @@

    - - {% for error in form.password.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + {% include 'snippets/form_errors.html' with errors_list=form.password.errors id="desc_password" %}
    From 0a621550b8863d7dda304864f09a12b4e0248baf Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:27:04 +0100 Subject: [PATCH 127/217] IP address form --- .../settings/ip_blocklist/ip_address_form.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bookwyrm/templates/settings/ip_blocklist/ip_address_form.html b/bookwyrm/templates/settings/ip_blocklist/ip_address_form.html index c8a4c3e74..4a776987f 100644 --- a/bookwyrm/templates/settings/ip_blocklist/ip_address_form.html +++ b/bookwyrm/templates/settings/ip_blocklist/ip_address_form.html @@ -20,16 +20,16 @@
    - +
    - {% for error in form.address.errors %} -

    {{ error | escape }}

    - {% endfor %} + {% include 'snippets/form_errors.html' with errors_list=form.address.errors id="desc_address" %}
    - +
    From 5d0c6bdde24d9964848826bdf12f5683145655d6 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:27:25 +0100 Subject: [PATCH 128/217] Edit instance form --- .../settings/federation/edit_instance.html | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/bookwyrm/templates/settings/federation/edit_instance.html b/bookwyrm/templates/settings/federation/edit_instance.html index 7c2e6be66..0a67895cc 100644 --- a/bookwyrm/templates/settings/federation/edit_instance.html +++ b/bookwyrm/templates/settings/federation/edit_instance.html @@ -27,11 +27,12 @@
    - - - {% for error in form.server_name.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.server_name.errors id="desc_server_name" %}
    @@ -49,29 +50,37 @@
    - - - {% for error in form.application_type.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.application_type.errors id="desc_application_type" %}
    - - - {% for error in form.application_version.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.application_version.errors id="desc_application_version" %}
    - - + +
    - + {% endblock %} From a6760cabc86d99b23bda32e36464a4a913aa7c3c Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:28:29 +0100 Subject: [PATCH 129/217] Email domain form --- bookwyrm/forms.py | 5 +++++ bookwyrm/templates/settings/email_blocklist/domain_form.html | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 88820c8f1..ddb02d937 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -383,6 +383,11 @@ class EmailBlocklistForm(CustomForm): class Meta: model = models.EmailBlocklist fields = ["domain"] + widgets = { + "avatar": forms.TextInput( + attrs={'aria-describedby': "desc_domain"} + ), + } class IPBlocklistForm(CustomForm): diff --git a/bookwyrm/templates/settings/email_blocklist/domain_form.html b/bookwyrm/templates/settings/email_blocklist/domain_form.html index e93337495..cebc97c85 100644 --- a/bookwyrm/templates/settings/email_blocklist/domain_form.html +++ b/bookwyrm/templates/settings/email_blocklist/domain_form.html @@ -17,10 +17,8 @@ {{ form.domain }}
    - {% for error in form.domain.errors %} -

    {{ error | escape }}

    - {% endfor %} + {% include 'snippets/form_errors.html' with errors_list=form.domain.errors id="desc_domain" %}
    From 659d13d0a60e80ac17e28ba2c41a295fb2b73422 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:28:51 +0100 Subject: [PATCH 130/217] Announcement form --- bookwyrm/forms.py | 20 +++++++ .../announcements/announcement_form.html | 58 +++++++++++-------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index ddb02d937..e8136a54f 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -359,6 +359,26 @@ class AnnouncementForm(CustomForm): class Meta: model = models.Announcement exclude = ["remote_id"] + widgets = { + "preview": forms.TextInput( + attrs={"aria-describedby": "desc_preview"} + ), + "content": forms.Textarea( + attrs={"aria-describedby": "desc_content"} + ), + "event_date": forms.SelectDateWidget( + attrs={"aria-describedby": "desc_event_date"} + ), + "start_date": forms.SelectDateWidget( + attrs={"aria-describedby": "desc_start_date"} + ), + "end_date": forms.SelectDateWidget( + attrs={"aria-describedby": "desc_end_date"} + ), + "active": forms.CheckboxInput( + attrs={"aria-describedby": "desc_active"} + ), + } class ListForm(CustomForm): diff --git a/bookwyrm/templates/settings/announcements/announcement_form.html b/bookwyrm/templates/settings/announcements/announcement_form.html index ffdbfc2fd..8f68e2555 100644 --- a/bookwyrm/templates/settings/announcements/announcement_form.html +++ b/bookwyrm/templates/settings/announcements/announcement_form.html @@ -13,60 +13,68 @@ {% csrf_token %}

    - + {{ form.preview }} - {% for error in form.preview.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.preview.errors id="desc_preview" %}

    - + {{ form.content }} - {% for error in form.content.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.content.errors id="desc_content" %}

    - + - {% for error in form.event_date.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.event_date.errors id="desc_event_date" %}

    - + - {% for error in form.start_date.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.start_date.errors id="desc_start_date" %}

    - + - {% for error in form.end_date.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.end_date.errors id="desc_end_date" %}

    - + {{ form.active }} - {% for error in form.active.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.active.errors id="desc_active" %}

    - +
    {% endblock %} From 63d31b8623d5eb084b049b5acbf8ae0a91da8408 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:29:22 +0100 Subject: [PATCH 131/217] Edit book form --- bookwyrm/forms.py | 61 ++++- .../templates/book/edit/edit_book_form.html | 229 ++++++++++-------- 2 files changed, 194 insertions(+), 96 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index e8136a54f..3f46be348 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -218,6 +218,65 @@ class EditionForm(CustomForm): "connector", "search_vector", ] + widgets = { + "title": forms.TextInput( + attrs={"aria-describedby": "desc_title"} + ), + "subtitle": forms.TextInput( + attrs={"aria-describedby": "desc_subtitle"} + ), + "description": forms.Textarea( + attrs={"aria-describedby": "desc_description"} + ), + "series": forms.TextInput( + attrs={"aria-describedby": "desc_series"} + ), + "series_number": forms.TextInput( + attrs={"aria-describedby": "desc_series_number"} + ), + "languages": forms.TextInput( + attrs={"aria-describedby": "desc_languages_help desc_languages"} + ), + "publishers": forms.TextInput( + attrs={"aria-describedby": "desc_publishers_help desc_publishers"} + ), + "first_published_date": forms.SelectDateWidget( + attrs={"aria-describedby": "desc_first_published_date"} + ), + "published_date": forms.SelectDateWidget( + attrs={"aria-describedby": "desc_published_date"} + ), + "cover": ClearableFileInputWithWarning( + attrs={"aria-describedby": "desc_cover"} + ), + "physical_format": forms.Select( + attrs={"aria-describedby": "desc_physical_format"} + ), + "physical_format_detail": forms.TextInput( + attrs={"aria-describedby": "desc_physical_format_detail"} + ), + "pages": forms.NumberInput( + attrs={"aria-describedby": "desc_pages"} + ), + "isbn_13": forms.TextInput( + attrs={"aria-describedby": "desc_isbn_13"} + ), + "isbn_10": forms.TextInput( + attrs={"aria-describedby": "desc_isbn_10"} + ), + "openlibrary_key": forms.TextInput( + attrs={"aria-describedby": "desc_openlibrary_key"} + ), + "inventaire_id": forms.TextInput( + attrs={"aria-describedby": "desc_inventaire_id"} + ), + "oclc_number": forms.TextInput( + attrs={"aria-describedby": "desc_oclc_number"} + ), + "ASIN": forms.TextInput( + attrs={"aria-describedby": "desc_ASIN"} + ), + } class AuthorForm(CustomForm): @@ -268,7 +327,7 @@ class AuthorForm(CustomForm): attrs={"aria-describedby": "desc_goodreads_key"} ), } - + class ImportForm(forms.Form): csv_file = forms.FileField() diff --git a/bookwyrm/templates/book/edit/edit_book_form.html b/bookwyrm/templates/book/edit/edit_book_form.html index 982bb56d2..feebb803c 100644 --- a/bookwyrm/templates/book/edit/edit_book_form.html +++ b/bookwyrm/templates/book/edit/edit_book_form.html @@ -12,106 +12,125 @@
    -

    {% trans "Metadata" %}

    +

    + {% trans "Metadata" %} +

    - - - {% for error in form.title.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.title.errors id="desc_title" %}
    - - - {% for error in form.subtitle.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.subtitle.errors id="desc_subtitle" %}
    - + {{ form.description }} - {% for error in form.description.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.description.errors id="desc_description" %}
    - - - {% for error in form.series.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.series.errors id="desc_series" %}
    - + {{ form.series_number }} - {% for error in form.series_number.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.series_number.errors id="desc_series_number" %}
    - + {{ form.languages }} - {% trans "Separate multiple values with commas." %} - {% for error in form.languages.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% trans "Separate multiple values with commas." %} + + + {% include 'snippets/form_errors.html' with errors_list=form.languages.errors id="desc_languages" %}
    -

    {% trans "Publication" %}

    +

    + {% trans "Publication" %} +

    - + {{ form.publishers }} - {% trans "Separate multiple values with commas." %} - {% for error in form.publishers.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% trans "Separate multiple values with commas." %} + + + {% include 'snippets/form_errors.html' with errors_list=form.publishers.errors id="desc_publishers" %}
    - - - {% for error in form.first_published_date.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.first_published_date.errors id="desc_first_published_date" %}
    - - - {% for error in form.published_date.errors %} -

    {{ error | escape }}

    - {% endfor %} + + + + {% include 'snippets/form_errors.html' with errors_list=form.published_date.errors id="desc_published_date" %}
    -

    {% trans "Authors" %}

    +

    + {% trans "Authors" %} +

    {% if book.authors.exists %}
    {% for author in book.authors.all %}
    -

    +

    {% blocktrans with name=author.name %}Author page for {{ name }}{% endblocktrans %}

    @@ -119,9 +138,13 @@
    {% endif %}
    - - - {% trans "Separate multiple values with commas." %} + + + + {% trans "Separate multiple values with commas." %} +
    @@ -129,7 +152,9 @@
    -

    {% trans "Cover" %}

    +

    + {% trans "Cover" %} +

    {% if book.cover %} @@ -140,108 +165,122 @@
    - + {{ form.cover }}
    - +
    - {% for error in form.cover.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.cover.errors id="desc_cover" %}
    -

    {% trans "Physical Properties" %}

    +

    + {% trans "Physical Properties" %} +

    - +
    {{ form.physical_format }}
    - {% for error in form.physical_format.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.physical_format.errors id="desc_physical_format" %}
    - + {{ form.physical_format_detail }} - {% for error in form.physical_format_detail.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.physical_format_detail.errors id="desc_physical_format_detail" %}
    - + {{ form.pages }} - {% for error in form.pages.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.pages.errors id="desc_pages" %}
    -

    {% trans "Book Identifiers" %}

    +

    + {% trans "Book Identifiers" %} +

    - + {{ form.isbn_13 }} - {% for error in form.isbn_13.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.isbn_13.errors id="desc_isbn_13" %}
    - + {{ form.isbn_10 }} - {% for error in form.isbn_10.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.isbn_10.errors id="desc_isbn_10" %}
    - + {{ form.openlibrary_key }} - {% for error in form.openlibrary_key.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.openlibrary_key.errors id="desc_openlibrary_key" %}
    - + {{ form.inventaire_id }} - {% for error in form.inventaire_id.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.inventaire_id.errors id="desc_inventaire_id" %}
    - + {{ form.oclc_number }} - {% for error in form.oclc_number.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.oclc_number.errors id="desc_oclc_number" %}
    - + {{ form.asin }} - {% for error in form.ASIN.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.ASIN.errors id="desc_ASIN" %}
    From 3eb4dfdc9be1cb4bc8b7e7ce718a030fa9ce4985 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:29:36 +0100 Subject: [PATCH 132/217] Get started user form --- bookwyrm/templates/get_started/profile.html | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/bookwyrm/templates/get_started/profile.html b/bookwyrm/templates/get_started/profile.html index 90cdb4104..ef33afac2 100644 --- a/bookwyrm/templates/get_started/profile.html +++ b/bookwyrm/templates/get_started/profile.html @@ -14,16 +14,14 @@
    - {% for error in form.name.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.name.errors id="desc_name" %}
    - {% for error in form.summary.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.summary.errors id="desc_summary" %}
    @@ -31,9 +29,8 @@
    {{ form.avatar }} - {% for error in form.avatar.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=form.avatar.errors id="desc_avatar" %}
    From 3cf9660df30f4eec6f4779029ce33cbf3752bf0f Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:29:56 +0100 Subject: [PATCH 133/217] Login form --- bookwyrm/templates/landing/layout.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templates/landing/layout.html b/bookwyrm/templates/landing/layout.html index 0d6f231c1..56985768f 100644 --- a/bookwyrm/templates/landing/layout.html +++ b/bookwyrm/templates/landing/layout.html @@ -65,10 +65,9 @@ {% csrf_token %}
    - - {% for error in request_form.email.errors %} -

    {{ error|escape }}

    - {% endfor %} + + + {% include 'snippets/form_errors.html' with errors_list=request_form.email.errors id="desc_request_email" %}
    From 80535a3b0caee396b82ca39207a4d03e251c9174 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:30:14 +0100 Subject: [PATCH 134/217] Login form --- bookwyrm/templates/landing/login.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templates/landing/login.html b/bookwyrm/templates/landing/login.html index 95baa06de..c9ac25261 100644 --- a/bookwyrm/templates/landing/login.html +++ b/bookwyrm/templates/landing/login.html @@ -26,11 +26,10 @@
    - +
    - {% for error in login_form.password.errors %} -

    {{ error | escape }}

    - {% endfor %} + + {% include 'snippets/form_errors.html' with errors_list=login_form.password.errors id="desc_password" %}
    From 43072a357f2f100907dafc608f9319444dc16f48 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:30:23 +0100 Subject: [PATCH 135/217] Password reset form --- .../templates/landing/password_reset.html | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/bookwyrm/templates/landing/password_reset.html b/bookwyrm/templates/landing/password_reset.html index be1dccf81..8348efd4f 100644 --- a/bookwyrm/templates/landing/password_reset.html +++ b/bookwyrm/templates/landing/password_reset.html @@ -8,21 +8,33 @@

    {% trans "Reset Password" %}

    - {% for error in errors %} -

    {{ error }}

    - {% endfor %} + + {% if errors %} +
    + {% for error in errors %} +

    + {{ error }} +

    + {% endfor %} +
    + + {% endif %}
    {% csrf_token %}
    - +
    - +
    - +
    - +
    From 4d93545d885400cc6370e2410b5311d1502e2dd5 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 29 Nov 2021 23:31:05 +0100 Subject: [PATCH 136/217] Lint forms --- bookwyrm/forms.py | 64 ++++++++++++----------------------------------- 1 file changed, 16 insertions(+), 48 deletions(-) diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 3f46be348..aff1e29cb 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -219,18 +219,12 @@ class EditionForm(CustomForm): "search_vector", ] widgets = { - "title": forms.TextInput( - attrs={"aria-describedby": "desc_title"} - ), - "subtitle": forms.TextInput( - attrs={"aria-describedby": "desc_subtitle"} - ), + "title": forms.TextInput(attrs={"aria-describedby": "desc_title"}), + "subtitle": forms.TextInput(attrs={"aria-describedby": "desc_subtitle"}), "description": forms.Textarea( attrs={"aria-describedby": "desc_description"} ), - "series": forms.TextInput( - attrs={"aria-describedby": "desc_series"} - ), + "series": forms.TextInput(attrs={"aria-describedby": "desc_series"}), "series_number": forms.TextInput( attrs={"aria-describedby": "desc_series_number"} ), @@ -255,15 +249,9 @@ class EditionForm(CustomForm): "physical_format_detail": forms.TextInput( attrs={"aria-describedby": "desc_physical_format_detail"} ), - "pages": forms.NumberInput( - attrs={"aria-describedby": "desc_pages"} - ), - "isbn_13": forms.TextInput( - attrs={"aria-describedby": "desc_isbn_13"} - ), - "isbn_10": forms.TextInput( - attrs={"aria-describedby": "desc_isbn_10"} - ), + "pages": forms.NumberInput(attrs={"aria-describedby": "desc_pages"}), + "isbn_13": forms.TextInput(attrs={"aria-describedby": "desc_isbn_13"}), + "isbn_10": forms.TextInput(attrs={"aria-describedby": "desc_isbn_10"}), "openlibrary_key": forms.TextInput( attrs={"aria-describedby": "desc_openlibrary_key"} ), @@ -273,9 +261,7 @@ class EditionForm(CustomForm): "oclc_number": forms.TextInput( attrs={"aria-describedby": "desc_oclc_number"} ), - "ASIN": forms.TextInput( - attrs={"aria-describedby": "desc_ASIN"} - ), + "ASIN": forms.TextInput(attrs={"aria-describedby": "desc_ASIN"}), } @@ -296,24 +282,14 @@ class AuthorForm(CustomForm): "goodreads_key", ] widgets = { - "name": forms.TextInput( - attrs={"aria-describedby": "desc_name"} - ), - "aliases": forms.TextInput( - attrs={"aria-describedby": "desc_aliases"} - ), - "bio": forms.Textarea( - attrs={"aria-describedby": "desc_bio"} - ), + "name": forms.TextInput(attrs={"aria-describedby": "desc_name"}), + "aliases": forms.TextInput(attrs={"aria-describedby": "desc_aliases"}), + "bio": forms.Textarea(attrs={"aria-describedby": "desc_bio"}), "wikipedia_link": forms.TextInput( attrs={"aria-describedby": "desc_wikipedia_link"} ), - "born": forms.SelectDateWidget( - attrs={"aria-describedby": "desc_born"} - ), - "died": forms.SelectDateWidget( - attrs={"aria-describedby": "desc_died"} - ), + "born": forms.SelectDateWidget(attrs={"aria-describedby": "desc_born"}), + "died": forms.SelectDateWidget(attrs={"aria-describedby": "desc_died"}), "oepnlibrary_key": forms.TextInput( attrs={"aria-describedby": "desc_oepnlibrary_key"} ), @@ -419,12 +395,8 @@ class AnnouncementForm(CustomForm): model = models.Announcement exclude = ["remote_id"] widgets = { - "preview": forms.TextInput( - attrs={"aria-describedby": "desc_preview"} - ), - "content": forms.Textarea( - attrs={"aria-describedby": "desc_content"} - ), + "preview": forms.TextInput(attrs={"aria-describedby": "desc_preview"}), + "content": forms.Textarea(attrs={"aria-describedby": "desc_content"}), "event_date": forms.SelectDateWidget( attrs={"aria-describedby": "desc_event_date"} ), @@ -434,9 +406,7 @@ class AnnouncementForm(CustomForm): "end_date": forms.SelectDateWidget( attrs={"aria-describedby": "desc_end_date"} ), - "active": forms.CheckboxInput( - attrs={"aria-describedby": "desc_active"} - ), + "active": forms.CheckboxInput(attrs={"aria-describedby": "desc_active"}), } @@ -463,9 +433,7 @@ class EmailBlocklistForm(CustomForm): model = models.EmailBlocklist fields = ["domain"] widgets = { - "avatar": forms.TextInput( - attrs={'aria-describedby': "desc_domain"} - ), + "avatar": forms.TextInput(attrs={"aria-describedby": "desc_domain"}), } From 386371baa3ee85e54c1f918c41297dc3c0681120 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Tue, 30 Nov 2021 12:42:52 +1100 Subject: [PATCH 137/217] improve a11y on notifications Also change close link to a button. Co-authored-by: Joachim --- bookwyrm/templates/ostatus/error.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bookwyrm/templates/ostatus/error.html b/bookwyrm/templates/ostatus/error.html index 085fa3454..99a2a9acb 100644 --- a/bookwyrm/templates/ostatus/error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -27,34 +27,34 @@
    {% elif error == 'ostatus_subscribe' %} -
    +

    {% blocktrans %}Something went wrong trying to follow {{ account }}{% endblocktrans %}

    {% trans 'Check you have the correct username before trying again.' %}

    {% elif error == 'remote_subscribe' %} -
    +

    {% blocktrans %}Something went wrong trying to follow from {{ account }}{% endblocktrans %}

    {% trans 'Check you have the correct username before trying again.' %}

    {% elif error == 'is_blocked' %} -
    +

    {% blocktrans %}You have blocked {{ account }}{% endblocktrans %}

    {% elif error == 'has_blocked' %} -
    +

    {% blocktrans %}{{ account }} has blocked you{% endblocktrans %}

    {% elif error == 'already_following' %} -
    +

    {% blocktrans %}You are already following {{ account }}{% endblocktrans %}

    {% elif error == 'already_requested' %} -
    +

    {% blocktrans %}You have already requested to follow {{ account }}{% endblocktrans %}

    {% endif %}
    - Close window +
    {% endblock %} From 4ee234258a15edb56485306480cb141f291e6c1b Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Tue, 30 Nov 2021 12:47:04 +1100 Subject: [PATCH 138/217] remove OG meta in ostatus template It's just a temporary popup so would be weird to share and just gunks things up. Co-authored-by: Joachim --- bookwyrm/templates/ostatus/template.html | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/bookwyrm/templates/ostatus/template.html b/bookwyrm/templates/ostatus/template.html index 04e432aaa..68284a35f 100644 --- a/bookwyrm/templates/ostatus/template.html +++ b/bookwyrm/templates/ostatus/template.html @@ -17,20 +17,6 @@ - {% if preview_images_enabled is True %} - - {% else %} - - {% endif %} - - - - - - {% block opengraph_images %} - {% include 'snippets/opengraph_images.html' %} - {% endblock %} - - - - - - -{% block scripts %}{% endblock %} diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index 50a7ae6d1..bc85e678e 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -222,7 +222,51 @@
    -{% include 'components/footer.html' %} + + + + + + + + +{% block scripts %}{% endblock %} From 7848ff792766b67d171e27dcab13f485cbf23bd4 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Tue, 30 Nov 2021 20:46:41 +1100 Subject: [PATCH 140/217] fix translation strings --- bookwyrm/templates/ostatus/remote_follow.html | 11 +++++++---- bookwyrm/templates/ostatus/subscribe.html | 10 +++++----- bookwyrm/templates/ostatus/success.html | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/bookwyrm/templates/ostatus/remote_follow.html b/bookwyrm/templates/ostatus/remote_follow.html index 6a4e565ac..96c7f9452 100644 --- a/bookwyrm/templates/ostatus/remote_follow.html +++ b/bookwyrm/templates/ostatus/remote_follow.html @@ -2,11 +2,12 @@ {% load i18n %} {% load utilities %} +{% block heading %} +{% blocktrans with username=user.localname sitename=site.name %}Follow {{ username }} on the fediverse{% endblocktrans %} +{% endblock %} + {% block content %}
    -
    -

    {% blocktrans %}Follow {{ user.display_name }} on the fediverse{% endblocktrans %}

    -
    @@ -24,11 +25,13 @@ @{{ user|username }} -

    {% blocktrans %}Follow {{ user.display_name }} from another Fediverse account like Bookwyrm, Mastodon, or Pleroma.{% endblocktrans %}

    +
    +

    {% blocktrans with username=user.display_name %}Follow {{ username }} from another Fediverse account like Bookwyrm, Mastodon, or Pleroma.{% endblocktrans %}

    +
    diff --git a/bookwyrm/templates/ostatus/subscribe.html b/bookwyrm/templates/ostatus/subscribe.html index d41ce6743..51dec4382 100644 --- a/bookwyrm/templates/ostatus/subscribe.html +++ b/bookwyrm/templates/ostatus/subscribe.html @@ -5,11 +5,11 @@ {% block title %} {% if not request.user.is_authenticated %} -{% trans "Log in to " %} +{% blocktrans with sitename=site.name %}Log in to {{ sitename }}{% endblocktrans %} {% elif error %} -{% trans "Error following from " %} +{% blocktrans with sitename=site.name %}Error following from {{ sitename }}{% endblocktrans %} {% else %} -{% trans "Follow from " %} +{% blocktrans with sitename=site.name %}Follow from {{ sitename }}{% endblocktrans %} {% endif %} {% endblock %} @@ -19,7 +19,7 @@ {% elif error %} {% trans 'Uh oh...' %} {% else %} -{% trans 'Follow from ' %}{{ site.name }} +{% blocktrans with sitename=site.name %}Follow from {{ sitename }}{% endblocktrans %} {% endif %} {% endblock %} @@ -48,7 +48,7 @@ {% csrf_token %} - +
    diff --git a/bookwyrm/templates/ostatus/success.html b/bookwyrm/templates/ostatus/success.html index 89f662735..a652989be 100644 --- a/bookwyrm/templates/ostatus/success.html +++ b/bookwyrm/templates/ostatus/success.html @@ -25,7 +25,7 @@

    - {% trans 'You are now following ' %}{{ user.display_name }}! + {% blocktrans with display_name=user.display_name %}You are now following {{ display_name }}!{% endblocktrans %}

    From 080fa72c84b6608d0788e2fc1b31cf0e34ed2b1c Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Tue, 30 Nov 2021 21:01:07 +1100 Subject: [PATCH 141/217] ostatus template fixes - remove unnecessary links - remove footer - remove unnecessary JS scripts - make block title and block heading empty --- bookwyrm/templates/ostatus/template.html | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/bookwyrm/templates/ostatus/template.html b/bookwyrm/templates/ostatus/template.html index 68284a35f..8d2d193ec 100644 --- a/bookwyrm/templates/ostatus/template.html +++ b/bookwyrm/templates/ostatus/template.html @@ -7,16 +7,11 @@ - {% block title %}{% endblock %}{{ site.name }} + {% block title %}{% endblock %} - - - - - + From 461c35f416e1838c470824d03f10c8eed8a7ff73 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Tue, 30 Nov 2021 21:02:39 +1100 Subject: [PATCH 142/217] fix buttons --- bookwyrm/templates/ostatus/error.html | 2 +- bookwyrm/templates/ostatus/success.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/ostatus/error.html b/bookwyrm/templates/ostatus/error.html index 99a2a9acb..0c8d6f768 100644 --- a/bookwyrm/templates/ostatus/error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -55,6 +55,6 @@ {% endif %}
    - +
    {% endblock %} diff --git a/bookwyrm/templates/ostatus/success.html b/bookwyrm/templates/ostatus/success.html index a652989be..a4f78ace8 100644 --- a/bookwyrm/templates/ostatus/success.html +++ b/bookwyrm/templates/ostatus/success.html @@ -30,6 +30,6 @@
    - Close window +
    {% endblock %} From 9be1a8f4557e98e9bfe4aee072f074fed3fc4d5a Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Wed, 1 Dec 2021 07:45:30 +1100 Subject: [PATCH 143/217] keep close button simple --- bookwyrm/templates/ostatus/error.html | 2 +- bookwyrm/templates/ostatus/success.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/ostatus/error.html b/bookwyrm/templates/ostatus/error.html index 0c8d6f768..b5a3bf406 100644 --- a/bookwyrm/templates/ostatus/error.html +++ b/bookwyrm/templates/ostatus/error.html @@ -55,6 +55,6 @@ {% endif %}
    - +
    {% endblock %} diff --git a/bookwyrm/templates/ostatus/success.html b/bookwyrm/templates/ostatus/success.html index a4f78ace8..66577e83f 100644 --- a/bookwyrm/templates/ostatus/success.html +++ b/bookwyrm/templates/ostatus/success.html @@ -30,6 +30,6 @@
    - +
    {% endblock %} From 66e414be3ca8b4de8426d3acc49608a7bd614fae Mon Sep 17 00:00:00 2001 From: Chad Nelson Date: Tue, 30 Nov 2021 17:21:28 -0500 Subject: [PATCH 144/217] Standardize JS, use button, & filter empty authors --- bookwyrm/static/js/bookwyrm.js | 11 ++++++++++- bookwyrm/templates/book/edit/edit_book_form.html | 2 +- bookwyrm/views/books/edit_book.py | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index bf5efb465..e18087eeb 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -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) + + )) } /** @@ -369,7 +376,9 @@ let BookWyrm = new class { } } - duplicateInput (input_id ) { + 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 diff --git a/bookwyrm/templates/book/edit/edit_book_form.html b/bookwyrm/templates/book/edit/edit_book_form.html index 841a3c53c..25d24e43d 100644 --- a/bookwyrm/templates/book/edit/edit_book_form.html +++ b/bookwyrm/templates/book/edit/edit_book_form.html @@ -128,7 +128,7 @@ {% endfor %} - {% trans "Add Another Author" %} + diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index 0bacd6074..917271fcb 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -43,8 +43,8 @@ class EditBook(View): if not form.is_valid(): return TemplateResponse(request, "book/edit/edit_book.html", data) - add_author = request.POST.getlist("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"] = [] From 91997b6f4c5874dfe53bea15df4f23fcdbaad814 Mon Sep 17 00:00:00 2001 From: Chad Nelson Date: Tue, 30 Nov 2021 17:42:31 -0500 Subject: [PATCH 145/217] Linting after merge conflict --- bookwyrm/views/books/edit_book.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/views/books/edit_book.py b/bookwyrm/views/books/edit_book.py index 930becac2..755c25b4c 100644 --- a/bookwyrm/views/books/edit_book.py +++ b/bookwyrm/views/books/edit_book.py @@ -57,7 +57,7 @@ class EditBook(View): data["add_author"] = add_author data["author_matches"] = [] data["isni_matches"] = [] - + for author in add_author: if not author: continue From 2602ae42b02c243e4550cda7407eec86009aaa6e Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Wed, 1 Dec 2021 20:07:52 +1100 Subject: [PATCH 146/217] add translation strings - add logic when default shelves used - add trans strings in a few spots they were missing --- bookwyrm/templates/directory/directory.html | 4 ++-- bookwyrm/templates/get_started/book_preview.html | 9 +++++++-- bookwyrm/templates/search/book.html | 2 +- bookwyrm/templates/shelf/shelf.html | 5 ++++- bookwyrm/templates/snippets/shelf_selector.html | 9 ++++++++- bookwyrm/templates/user/user.html | 11 ++++++++--- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/bookwyrm/templates/directory/directory.html b/bookwyrm/templates/directory/directory.html index 9753c4c0f..c3ddb3c5c 100644 --- a/bookwyrm/templates/directory/directory.html +++ b/bookwyrm/templates/directory/directory.html @@ -18,7 +18,7 @@

    {% csrf_token %} - +

    {% url 'prefs-profile' as path %} {% blocktrans with path=path %}You can opt-out at any time in your profile settings.{% endblocktrans %} @@ -28,7 +28,7 @@

    {% trans "Dismiss message" as button_text %}
    diff --git a/bookwyrm/templates/get_started/book_preview.html b/bookwyrm/templates/get_started/book_preview.html index 893e7593a..8a20d0d77 100644 --- a/bookwyrm/templates/get_started/book_preview.html +++ b/bookwyrm/templates/get_started/book_preview.html @@ -4,9 +4,14 @@
    diff --git a/bookwyrm/templates/search/book.html b/bookwyrm/templates/search/book.html index 704f055bf..66adb8c83 100644 --- a/bookwyrm/templates/search/book.html +++ b/bookwyrm/templates/search/book.html @@ -39,7 +39,7 @@
    diff --git a/bookwyrm/templates/shelf/shelf.html b/bookwyrm/templates/shelf/shelf.html index 01d41aa07..0184ab1d8 100644 --- a/bookwyrm/templates/shelf/shelf.html +++ b/bookwyrm/templates/shelf/shelf.html @@ -80,7 +80,10 @@

    - {{ shelf.name }} + {% if shelf.identifier == 'to-read' %}{% trans "To Read" %} + {% elif shelf.identifier == 'reading' %}{% trans "Currently Reading" %} + {% elif shelf.identifier == 'read' %}{% trans "Read" %} + {% else %}{{ shelf.name }}{% endif %} {% include 'snippets/privacy-icons.html' with item=shelf %} diff --git a/bookwyrm/templates/snippets/shelf_selector.html b/bookwyrm/templates/snippets/shelf_selector.html index ca5a39f6e..2bb5e2536 100644 --- a/bookwyrm/templates/snippets/shelf_selector.html +++ b/bookwyrm/templates/snippets/shelf_selector.html @@ -13,7 +13,14 @@ - + {% endfor %} diff --git a/bookwyrm/templates/user/user.html b/bookwyrm/templates/user/user.html index 36e646aa9..9e75cefc0 100755 --- a/bookwyrm/templates/user/user.html +++ b/bookwyrm/templates/user/user.html @@ -29,8 +29,13 @@
    {% for shelf in shelves %}
    -

    {{ shelf.name }} - {% if shelf.size > 3 %}({% blocktrans with size=shelf.size %}View all {{ size }}{% endblocktrans %}){% endif %}

    +

    + {% if shelf.name == 'To Read' %}{% trans "To Read" %} + {% elif shelf.name == 'Currently Reading' %}{% trans "Currently Reading" %} + {% elif shelf.name == 'Read' %}{% trans "Read" %} + {% else %}{{ shelf.name }}{% endif %} + {% if shelf.size > 3 %}({% blocktrans with size=shelf.size %}View all {{ size }}{% endblocktrans %}){% endif %} +

    {% for book in shelf.books %}
    @@ -49,7 +54,7 @@ {% if goal %}
    -

    {% now 'Y' %} Reading Goal

    +

    {% now 'Y' %} {% trans 'Reading Goal' %}

    {% include 'snippets/goal_progress.html' with goal=goal %}
    {% endif %} From 8e6619294f1864b83a51457a9475567eace42055 Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Wed, 1 Dec 2021 21:02:25 +1100 Subject: [PATCH 147/217] oclc server sure is slow --- bookwyrm/utils/isni.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/utils/isni.py b/bookwyrm/utils/isni.py index a35c3f249..65d20c85c 100644 --- a/bookwyrm/utils/isni.py +++ b/bookwyrm/utils/isni.py @@ -19,7 +19,7 @@ def request_isni_data(search_index, search_term, max_records=5): "recordPacking": "xml", "sortKeys": "RLV,pica,0,,", } - result = requests.get("http://isni.oclc.org/sru/", params=query_params, timeout=10) + result = requests.get("http://isni.oclc.org/sru/", params=query_params, timeout=15) # the OCLC ISNI server asserts the payload is encoded # in latin1, but we know better result.encoding = "utf-8" From 5f10ccd9c7cb0f953b197bc5239515c5d33b0fa0 Mon Sep 17 00:00:00 2001 From: Olof Pettersson Date: Wed, 1 Dec 2021 14:18:28 +0100 Subject: [PATCH 148/217] Comment out trailing block ending For people installing an instance with only the reverse proxy server, the hidden trailing `}` at the end of the second server block is quite hard to catch and it took me a good while to figure it out. Having the entire server commented out makes the whole process more understandable in my opinion. --- nginx/production | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nginx/production b/nginx/production index 8a13413a6..3d9cfa5ae 100644 --- a/nginx/production +++ b/nginx/production @@ -17,7 +17,8 @@ server { # # redirect http to https # return 301 https://your-domain.com$request_uri; -# } +} + # # server { # listen [::]:443 ssl http2; @@ -54,7 +55,7 @@ server { # location /static/ { # alias /app/static/; # } -} +# } # Reverse-Proxy server # server { From 2ec6e566986de5ea4c85cf2ec43e002d58a9d4ac Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Thu, 2 Dec 2021 07:28:35 +1100 Subject: [PATCH 149/217] blocktrans for reading goal --- bookwyrm/templates/user/user.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/templates/user/user.html b/bookwyrm/templates/user/user.html index 9e75cefc0..ccc4a44ea 100755 --- a/bookwyrm/templates/user/user.html +++ b/bookwyrm/templates/user/user.html @@ -54,7 +54,8 @@ {% if goal %}
    -

    {% now 'Y' %} {% trans 'Reading Goal' %}

    + {% now 'Y' as current_year%} +

    {% blocktrans %}{{ current_year }} Reading Goal{% endblocktrans %}

    {% include 'snippets/goal_progress.html' with goal=goal %}
    {% endif %} From 0794f1a28642a85ef4bbf382823d7c34fff5e2cc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 2 Dec 2021 10:28:13 -0800 Subject: [PATCH 150/217] Updates locales --- bw-dev | 1 + locale/en_US/LC_MESSAGES/django.po | 92 +++++++++++++++++---------- locale/fr_FR/LC_MESSAGES/django.mo | Bin 44850 -> 65763 bytes locale/lt_LT/LC_MESSAGES/django.mo | Bin 65147 -> 65121 bytes locale/lt_LT/LC_MESSAGES/django.po | 22 +++---- locale/zh_Hans/LC_MESSAGES/django.mo | Bin 44096 -> 59480 bytes locale/zh_Hans/LC_MESSAGES/django.po | 66 +++++++++---------- 7 files changed, 103 insertions(+), 78 deletions(-) diff --git a/bw-dev b/bw-dev index 75c69662b..cfe8747fb 100755 --- a/bw-dev +++ b/bw-dev @@ -118,6 +118,7 @@ case "$CMD" in git checkout l10n_main locale/pt_BR git checkout l10n_main locale/zh_Hans git checkout l10n_main locale/zh_Hant + runweb django-admin makemessages --no-wrap --ignore=venv -l en_US $@ runweb django-admin compilemessages --ignore venv ;; build) diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index f5df1265d..5080502f5 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-17 18:03+0000\n" +"POT-Creation-Date: 2021-12-02 18:24+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -227,47 +227,51 @@ msgstr "" msgid "Something went wrong! Sorry about that." msgstr "" -#: bookwyrm/templates/author/author.html:17 #: bookwyrm/templates/author/author.html:18 +#: bookwyrm/templates/author/author.html:19 msgid "Edit Author" msgstr "" -#: bookwyrm/templates/author/author.html:34 +#: bookwyrm/templates/author/author.html:35 #: bookwyrm/templates/author/edit_author.html:43 msgid "Aliases:" msgstr "" -#: bookwyrm/templates/author/author.html:45 +#: bookwyrm/templates/author/author.html:46 msgid "Born:" msgstr "" -#: bookwyrm/templates/author/author.html:52 +#: bookwyrm/templates/author/author.html:53 msgid "Died:" msgstr "" -#: bookwyrm/templates/author/author.html:61 +#: bookwyrm/templates/author/author.html:62 msgid "Wikipedia" msgstr "" -#: bookwyrm/templates/author/author.html:69 +#: bookwyrm/templates/author/author.html:70 +msgid "View ISNI record" +msgstr "" + +#: bookwyrm/templates/author/author.html:78 #: bookwyrm/templates/book/book.html:94 msgid "View on OpenLibrary" msgstr "" -#: bookwyrm/templates/author/author.html:77 +#: bookwyrm/templates/author/author.html:86 #: bookwyrm/templates/book/book.html:97 msgid "View on Inventaire" msgstr "" -#: bookwyrm/templates/author/author.html:85 +#: bookwyrm/templates/author/author.html:94 msgid "View on LibraryThing" msgstr "" -#: bookwyrm/templates/author/author.html:93 +#: bookwyrm/templates/author/author.html:102 msgid "View on Goodreads" msgstr "" -#: bookwyrm/templates/author/author.html:108 +#: bookwyrm/templates/author/author.html:117 #, python-format msgid "Books by %(name)s" msgstr "" @@ -277,17 +281,17 @@ msgid "Edit Author:" msgstr "" #: bookwyrm/templates/author/edit_author.html:13 -#: bookwyrm/templates/book/edit/edit_book.html:18 +#: bookwyrm/templates/book/edit/edit_book.html:19 msgid "Added:" msgstr "" #: bookwyrm/templates/author/edit_author.html:14 -#: bookwyrm/templates/book/edit/edit_book.html:21 +#: bookwyrm/templates/book/edit/edit_book.html:22 msgid "Updated:" msgstr "" #: bookwyrm/templates/author/edit_author.html:16 -#: bookwyrm/templates/book/edit/edit_book.html:25 +#: bookwyrm/templates/book/edit/edit_book.html:26 msgid "Last edited by:" msgstr "" @@ -347,7 +351,7 @@ msgstr "" #: bookwyrm/templates/author/edit_author.html:118 #: bookwyrm/templates/book/book.html:140 -#: bookwyrm/templates/book/edit/edit_book.html:110 +#: bookwyrm/templates/book/edit/edit_book.html:121 #: bookwyrm/templates/book/readthrough.html:76 #: bookwyrm/templates/groups/form.html:24 #: bookwyrm/templates/lists/bookmark_button.html:15 @@ -366,8 +370,8 @@ msgstr "" #: bookwyrm/templates/author/edit_author.html:119 #: bookwyrm/templates/book/book.html:141 bookwyrm/templates/book/book.html:190 #: bookwyrm/templates/book/cover_modal.html:32 -#: bookwyrm/templates/book/edit/edit_book.html:112 -#: bookwyrm/templates/book/edit/edit_book.html:115 +#: bookwyrm/templates/book/edit/edit_book.html:123 +#: bookwyrm/templates/book/edit/edit_book.html:126 #: bookwyrm/templates/book/readthrough.html:77 #: bookwyrm/templates/groups/delete_group_modal.html:17 #: bookwyrm/templates/lists/delete_list_modal.html:17 @@ -513,56 +517,60 @@ msgstr "" msgid "Load cover from url:" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:5 -#: bookwyrm/templates/book/edit/edit_book.html:11 +#: bookwyrm/templates/book/edit/edit_book.html:6 +#: bookwyrm/templates/book/edit/edit_book.html:12 #, python-format msgid "Edit \"%(book_title)s\"" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:5 -#: bookwyrm/templates/book/edit/edit_book.html:13 +#: bookwyrm/templates/book/edit/edit_book.html:6 +#: bookwyrm/templates/book/edit/edit_book.html:14 msgid "Add Book" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:47 +#: bookwyrm/templates/book/edit/edit_book.html:48 msgid "Confirm Book Info" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:55 +#: bookwyrm/templates/book/edit/edit_book.html:56 #, python-format -msgid "Is \"%(name)s\" an existing author?" +msgid "Is \"%(name)s\" one of these authors?" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:64 -#, python-format -msgid "Author of %(book_title)s" +#: bookwyrm/templates/book/edit/edit_book.html:67 +#: bookwyrm/templates/book/edit/edit_book.html:69 +msgid "Author of " msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:68 +#: bookwyrm/templates/book/edit/edit_book.html:69 +msgid "Find more information at isni.org" +msgstr "" + +#: bookwyrm/templates/book/edit/edit_book.html:79 msgid "This is a new author" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:75 +#: bookwyrm/templates/book/edit/edit_book.html:86 #, python-format msgid "Creating a new author: %(name)s" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:82 +#: bookwyrm/templates/book/edit/edit_book.html:93 msgid "Is this an edition of an existing work?" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:90 +#: bookwyrm/templates/book/edit/edit_book.html:101 msgid "This is a new work" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:97 +#: bookwyrm/templates/book/edit/edit_book.html:108 #: bookwyrm/templates/groups/members.html:16 #: bookwyrm/templates/landing/password_reset.html:30 #: bookwyrm/templates/snippets/remove_from_group_button.html:16 msgid "Confirm" msgstr "" -#: bookwyrm/templates/book/edit/edit_book.html:99 +#: bookwyrm/templates/book/edit/edit_book.html:110 #: bookwyrm/templates/feed/status.html:9 msgid "Back" msgstr "" @@ -1016,6 +1024,22 @@ msgstr "" msgid "Learn more about %(site_name)s:" msgstr "" +#: bookwyrm/templates/email/moderation_report/html_content.html:6 +#: bookwyrm/templates/email/moderation_report/text_content.html:5 +#, python-format +msgid "@%(reporter)s has flagged behavior by @%(reportee)s for moderation. " +msgstr "" + +#: bookwyrm/templates/email/moderation_report/html_content.html:9 +#: bookwyrm/templates/email/moderation_report/text_content.html:7 +msgid "View report" +msgstr "" + +#: bookwyrm/templates/email/moderation_report/subject.html:2 +#, python-format +msgid "New report for %(site_name)s" +msgstr "" + #: bookwyrm/templates/email/password_reset/html_content.html:6 #: bookwyrm/templates/email/password_reset/text_content.html:4 #, python-format @@ -3842,7 +3866,7 @@ msgstr "" msgid "File exceeds maximum size: 10MB" msgstr "" -#: bookwyrm/templatetags/utilities.py:31 +#: bookwyrm/templatetags/utilities.py:34 #, python-format msgid "%(title)s: %(subtitle)s" msgstr "" diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index 4cdcbf8ea2a3ffdeed740317a055f435e5954b7c..cc69e82cf8477c385d869a23d3e81c5947773963 100644 GIT binary patch literal 65763 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 Vg;`>g&vx=owp=K`x%3^I000KmvCaSh delta 6487 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 diff --git a/locale/lt_LT/LC_MESSAGES/django.po b/locale/lt_LT/LC_MESSAGES/django.po index 16110b069..d2ec32981 100644 --- a/locale/lt_LT/LC_MESSAGES/django.po +++ b/locale/lt_LT/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-17 18:03+0000\n" -"PO-Revision-Date: 2021-11-22 08:50\n" +"PO-Revision-Date: 2021-11-29 13:53\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Lithuanian\n" "Language: lt\n" @@ -591,7 +591,7 @@ msgstr "Kalbos:" #: bookwyrm/templates/book/edit/edit_book_form.html:74 msgid "Publication" -msgstr "Paskelbimas" +msgstr "Leidimas" #: bookwyrm/templates/book/edit/edit_book_form.html:77 msgid "Publisher:" @@ -930,7 +930,7 @@ msgstr "%(username)s įvertino %(username)s reviewed %(book_title)s" -msgstr "%(username)s peržiūrėjo %(book_title)s" +msgstr "%(username)s apžvelgė %(book_title)s" #: bookwyrm/templates/discover/card-header.html:31 #, python-format @@ -1114,7 +1114,7 @@ msgstr "Šiuo metu skaitoma" #: bookwyrm/templates/snippets/shelve_button/shelve_button_options.html:12 #: bookwyrm/templates/user/books_header.html:8 msgid "Read" -msgstr "Perskaičiau" +msgstr "Perskaityta" #: bookwyrm/templates/feed/suggested_users.html:5 #: bookwyrm/templates/get_started/users.html:6 @@ -1483,7 +1483,7 @@ msgstr "Lentyna" #: bookwyrm/templates/import/manual_review.html:13 #: bookwyrm/templates/snippets/create_status.html:17 msgid "Review" -msgstr "Peržiūra" +msgstr "Apžvalga" #: bookwyrm/templates/import/import_status.html:119 msgid "Book" @@ -1513,7 +1513,7 @@ msgstr "Importuota" #: bookwyrm/templates/import/import_status.html:182 msgid "Needs manual review" -msgstr "Reikalingas manualus atsiliepimas" +msgstr "Reikalinga peržvelgti" #: bookwyrm/templates/import/import_status.html:195 msgid "Retry" @@ -2416,7 +2416,7 @@ msgstr[3] "%(display_count)s prašymai pakviesti" #: bookwyrm/templates/settings/dashboard/dashboard.html:65 msgid "Instance Activity" -msgstr "Pavyzdinė veikla" +msgstr "Serverio statistika" #: bookwyrm/templates/settings/dashboard/dashboard.html:83 msgid "Interval:" @@ -2436,7 +2436,7 @@ msgstr "Naudotojo prisijungimo veikla" #: bookwyrm/templates/settings/dashboard/dashboard.html:112 msgid "Status activity" -msgstr "Būsenos veikla" +msgstr "Būsenos" #: bookwyrm/templates/settings/dashboard/dashboard.html:118 msgid "Works created" @@ -3467,7 +3467,7 @@ msgstr "%(percent)s%% baigta!" #: bookwyrm/templates/snippets/goal_progress.html:12 #, python-format msgid "You've read %(read_count)s of %(goal_count)s books." -msgstr "Perskaitėte %(read_count)s iš %(goal_count)s knygų." +msgstr "Perskaityta %(read_count)s iš %(goal_count)s knygų." #: bookwyrm/templates/snippets/goal_progress.html:14 #, python-format @@ -3504,7 +3504,7 @@ msgstr "Viešas" #: bookwyrm/templates/snippets/privacy_select.html:14 #: bookwyrm/templates/snippets/privacy_select_no_followers.html:14 msgid "Unlisted" -msgstr "Nėra sąraše" +msgstr "Slaptas" #: bookwyrm/templates/snippets/privacy-icons.html:12 msgid "Followers-only" @@ -3873,7 +3873,7 @@ msgstr[3] "%(mutuals_display)s sekėjai, kuriuos sekate jūs" #: bookwyrm/templates/user/user_preview.html:38 msgid "No followers you follow" -msgstr "Jūs nieko nesekate" +msgstr "Jūs kartu nieko nesekate" #: bookwyrm/templates/widgets/clearable_file_input_with_warning.html:28 msgid "File exceeds maximum size: 10MB" diff --git a/locale/zh_Hans/LC_MESSAGES/django.mo b/locale/zh_Hans/LC_MESSAGES/django.mo index 1d1227f8092b70c68bb692fb532759090142aa83..3e559018804034a297286bed7c8c6828714c49c4 100644 GIT binary patch literal 59480 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�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 AMF0Q* delta 16954 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 diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index 1b86621df..e52dfc4f5 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: bookwyrm\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-17 18:03+0000\n" -"PO-Revision-Date: 2021-11-17 18:42\n" +"PO-Revision-Date: 2021-11-29 09:31\n" "Last-Translator: Mouse Reeve \n" "Language-Team: Chinese Simplified\n" "Language: zh\n" @@ -184,7 +184,7 @@ msgstr "Español(西班牙语)" #: bookwyrm/settings.py:168 msgid "Galego (Galician)" -msgstr "" +msgstr "Galego(加利西亚语)" #: bookwyrm/settings.py:169 msgid "Français (French)" @@ -192,11 +192,11 @@ msgstr "Français(法语)" #: bookwyrm/settings.py:170 msgid "Lietuvių (Lithuanian)" -msgstr "" +msgstr "Lietuvių(立陶宛语)" #: bookwyrm/settings.py:171 msgid "Português - Brasil (Brazilian Portuguese)" -msgstr "葡萄牙语-巴西(巴西的葡语)" +msgstr "Português - Brasil(巴西葡萄牙语)" #: bookwyrm/settings.py:172 msgid "简体中文 (Simplified Chinese)" @@ -906,12 +906,12 @@ msgstr "%(username)s 想要阅读 %(username)s finished reading %(book_title)s" -msgstr "" +msgstr "%(username)s 完成了 %(book_title)s 的阅读" #: bookwyrm/templates/discover/card-header.html:18 #, python-format msgid "%(username)s started reading %(book_title)s" -msgstr "" +msgstr "%(username)s 开始阅读 %(book_title)s" #: bookwyrm/templates/discover/card-header.html:23 #, python-format @@ -1395,11 +1395,11 @@ msgstr "导入状态" #: bookwyrm/templates/import/import_status.html:13 #: bookwyrm/templates/import/import_status.html:27 msgid "Retry Status" -msgstr "" +msgstr "重试状态" #: bookwyrm/templates/import/import_status.html:22 msgid "Imports" -msgstr "" +msgstr "导入" #: bookwyrm/templates/import/import_status.html:39 msgid "Import started:" @@ -1407,36 +1407,36 @@ msgstr "导入开始:" #: bookwyrm/templates/import/import_status.html:48 msgid "In progress" -msgstr "" +msgstr "正在进行" #: bookwyrm/templates/import/import_status.html:50 msgid "Refresh" -msgstr "" +msgstr "刷新" #: bookwyrm/templates/import/import_status.html:71 #, python-format msgid "%(display_counter)s item needs manual approval." msgid_plural "%(display_counter)s items need manual approval." -msgstr[0] "" +msgstr[0] "%(display_counter)s 项需要手动批准。" #: bookwyrm/templates/import/import_status.html:76 #: bookwyrm/templates/import/manual_review.html:8 msgid "Review items" -msgstr "" +msgstr "审阅项目" #: bookwyrm/templates/import/import_status.html:82 #, python-format msgid "%(display_counter)s item failed to import." msgid_plural "%(display_counter)s items failed to import." -msgstr[0] "" +msgstr[0] "%(display_counter)s 项导入失败。" #: bookwyrm/templates/import/import_status.html:88 msgid "View and troubleshoot failed items" -msgstr "" +msgstr "查看并排查失败项目" #: bookwyrm/templates/import/import_status.html:100 msgid "Row" -msgstr "" +msgstr "行" #: bookwyrm/templates/import/import_status.html:103 #: bookwyrm/templates/shelf/shelf.html:141 @@ -1446,7 +1446,7 @@ msgstr "标题" #: bookwyrm/templates/import/import_status.html:106 msgid "ISBN" -msgstr "" +msgstr "ISBN" #: bookwyrm/templates/import/import_status.html:109 #: bookwyrm/templates/shelf/shelf.html:142 @@ -1456,7 +1456,7 @@ msgstr "作者" #: bookwyrm/templates/import/import_status.html:112 msgid "Shelf" -msgstr "" +msgstr "书架" #: bookwyrm/templates/import/import_status.html:115 #: bookwyrm/templates/import/manual_review.html:13 @@ -1480,11 +1480,11 @@ msgstr "状态" #: bookwyrm/templates/import/import_status.html:130 msgid "Import preview unavailable." -msgstr "" +msgstr "导入预览不可用。" #: bookwyrm/templates/import/import_status.html:162 msgid "View imported review" -msgstr "" +msgstr "查看已导入的书评" #: bookwyrm/templates/import/import_status.html:176 msgid "Imported" @@ -1492,28 +1492,28 @@ msgstr "已导入" #: bookwyrm/templates/import/import_status.html:182 msgid "Needs manual review" -msgstr "" +msgstr "需要手动批准" #: bookwyrm/templates/import/import_status.html:195 msgid "Retry" -msgstr "" +msgstr "重试" #: bookwyrm/templates/import/import_status.html:213 msgid "This import is in an old format that is no longer supported. If you would like to troubleshoot missing items from this import, click the button below to update the import format." -msgstr "" +msgstr "此导入所用格式已不再受支持。 如果您想要在此次导入中排查缺失的项目,请点击下面的按钮来更新导入格式。" #: bookwyrm/templates/import/import_status.html:215 msgid "Update import" -msgstr "" +msgstr "更新导入" #: bookwyrm/templates/import/manual_review.html:5 #: bookwyrm/templates/import/troubleshoot.html:4 msgid "Import Troubleshooting" -msgstr "" +msgstr "导入排查" #: bookwyrm/templates/import/manual_review.html:21 msgid "Approving a suggestion will permanently add the suggested book to your shelves and associate your reading dates, reviews, and ratings with that book." -msgstr "" +msgstr "批准建议后,被提议的书将会永久添加到您的书架上并与您的阅读日期、书评、评分联系起来。" #: bookwyrm/templates/import/manual_review.html:58 #: bookwyrm/templates/lists/curate.html:57 @@ -1522,7 +1522,7 @@ msgstr "批准" #: bookwyrm/templates/import/manual_review.html:66 msgid "Reject" -msgstr "" +msgstr "驳回" #: bookwyrm/templates/import/tooltip.html:6 msgid "You can download your Goodreads data from the Import/Export page of your Goodreads account." @@ -1530,31 +1530,31 @@ msgstr "您可以从 open an issue if you are seeing unexpected failed items." -msgstr "" +msgstr "如果您看到意外失败的项目,请联系您的管理员或 发起一个 issue。" #: bookwyrm/templates/landing/about.html:7 bookwyrm/templates/layout.html:230 #, python-format From f6dfe3530a2ca7063a7d2c3ca023632a3756028c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 3 Dec 2021 09:58:14 -0800 Subject: [PATCH 151/217] Use book preview card for social media on status page --- bookwyrm/templates/feed/status.html | 12 ++++++++++++ bookwyrm/views/feed.py | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/bookwyrm/templates/feed/status.html b/bookwyrm/templates/feed/status.html index 5febf4e22..8dcad0886 100644 --- a/bookwyrm/templates/feed/status.html +++ b/bookwyrm/templates/feed/status.html @@ -2,6 +2,18 @@ {% load i18n %} {% load bookwyrm_tags %} +{% block opengraph_images %} + +{% firstof status.book status.mention_books.first as book %} +{% if book %} + {% include 'snippets/opengraph_images.html' with image=preview %} +{% else %} + {% include 'snippets/opengraph_images.html' %} +{% endif %} + +{% endblock %} + + {% block panel %}
    diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 7cf56d48f..ba6c3af52 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -177,12 +177,19 @@ class Status(View): params=[status.id, visible_thread, visible_thread], ) + preview = None + if hasattr(status, "book"): + preview = status.book.preview_image + elif status.mention_books.exists(): + preview = status.mention_books.first().preview_image + data = { **feed_page_data(request.user), **{ "status": status, "children": children, "ancestors": ancestors, + "preview": preview, }, } return TemplateResponse(request, "feed/status.html", data) From 3bd28afe93db282be61cbc4a50205a3b8179288e Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:06:07 +0100 Subject: [PATCH 152/217] Add unique embed_key to List model --- bookwyrm/migrations/0120_list_embed_key.py | 29 ++++++++++++++++++++++ bookwyrm/models/list.py | 9 +++++++ 2 files changed, 38 insertions(+) create mode 100644 bookwyrm/migrations/0120_list_embed_key.py diff --git a/bookwyrm/migrations/0120_list_embed_key.py b/bookwyrm/migrations/0120_list_embed_key.py new file mode 100644 index 000000000..40db1f0fe --- /dev/null +++ b/bookwyrm/migrations/0120_list_embed_key.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.5 on 2021-12-04 10:55 + +from django.db import migrations, models +import uuid + + +def gen_uuid(apps, schema_editor): + """sets an unique UUID for embed_key""" + book_lists = apps.get_model("bookwyrm", "List") + db_alias = schema_editor.connection.alias + for book_list in book_lists.objects.using(db_alias).all(): + book_list.embed_key = uuid.uuid4() + book_list.save(broadcast=False) + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0119_user_feed_status_types"), + ] + + operations = [ + migrations.AddField( + model_name="list", + name="embed_key", + field=models.UUIDField(editable=False, null=True, unique=True), + ), + migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop), + ] diff --git a/bookwyrm/models/list.py b/bookwyrm/models/list.py index 978a7a9b3..61cb41ef5 100644 --- a/bookwyrm/models/list.py +++ b/bookwyrm/models/list.py @@ -1,4 +1,6 @@ """ make a list of books!! """ +import uuid + from django.apps import apps from django.db import models from django.db.models import Q @@ -43,6 +45,7 @@ class List(OrderedCollectionMixin, BookWyrmModel): through="ListItem", through_fields=("book_list", "book"), ) + embed_key = models.UUIDField(unique=True, null=True, editable=False) activity_serializer = activitypub.BookList def get_remote_id(self): @@ -105,6 +108,12 @@ class List(OrderedCollectionMixin, BookWyrmModel): group=None, curation="closed" ) + def save(self, *args, **kwargs): + """on save, update embed_key and avoid clash with existing code""" + if not self.embed_key: + self.embed_key = uuid.uuid4() + return super(List, self).save(*args, **kwargs) + class ListItem(CollectionItemMixin, BookWyrmModel): """ok""" From d22167e105068f81acc3e78393af471532b25d53 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:07:21 +0100 Subject: [PATCH 153/217] Add EmbedList view with an X-Frame-Options exemption --- bookwyrm/views/list.py | 69 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index 97eaf9d6f..89e7fa465 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -7,13 +7,14 @@ from django.core.paginator import Paginator from django.db import IntegrityError, transaction from django.db.models import Avg, Count, DecimalField, Q, Max from django.db.models.functions import Coalesce -from django.http import HttpResponseBadRequest, HttpResponse +from django.http import HttpResponseBadRequest, HttpResponse, Http404 from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.urls import reverse from django.utils.decorators import method_decorator from django.views import View from django.views.decorators.http import require_POST +from django.views.decorators.clickjacking import xframe_options_exempt from bookwyrm import book_search, forms, models from bookwyrm.activitypub import ActivitypubResponse @@ -200,6 +201,64 @@ class List(View): return redirect(book_list.local_path) +class EmbedList(View): + """embeded book list page""" + + def get(self, request, list_id, list_key): + """display a book list""" + book_list = get_object_or_404(models.List, id=list_id) + + embed_key = str(book_list.embed_key.hex) + + if list_key != embed_key: + raise Http404() + + query = request.GET.get("q") + suggestions = None + + # sort_by shall be "order" unless a valid alternative is given + sort_by = request.GET.get("sort_by", "order") + if sort_by not in ("order", "title", "rating"): + sort_by = "order" + + # direction shall be "ascending" unless a valid alternative is given + direction = request.GET.get("direction", "ascending") + if direction not in ("ascending", "descending"): + direction = "ascending" + + directional_sort_by = { + "order": "order", + "title": "book__title", + "rating": "average_rating", + }[sort_by] + if direction == "descending": + directional_sort_by = "-" + directional_sort_by + + items = book_list.listitem_set.prefetch_related("user", "book", "book__authors") + if sort_by == "rating": + items = items.annotate( + average_rating=Avg( + Coalesce("book__review__rating", 0.0), + output_field=DecimalField(), + ) + ) + items = items.filter(approved=True).order_by(directional_sort_by) + + paginated = Paginator(items, PAGE_LENGTH) + + page = paginated.get_page(request.GET.get("page")) + + data = { + "list": book_list, + "items": page, + "page_range": paginated.get_elided_page_range( + page.number, on_each_side=2, on_ends=1 + ), + "query": query or "", + } + return TemplateResponse(request, "lists/embed-list.html", data) + + class Curate(View): """approve or discard list suggestsions""" @@ -447,3 +506,11 @@ def normalize_book_list_ordering(book_list_id, start=0, add_offset=0): if item.order != effective_order: item.order = effective_order item.save() + + +@xframe_options_exempt +def unsafe_embed_list(request, *args, **kwargs): + """allows the EmbedList view to be loaded through unsafe iframe origins""" + + embed_list_view = EmbedList.as_view() + return embed_list_view(request, *args, **kwargs) From 8ee09a2284734eed4d486d480d38fb67a31a324c Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:07:38 +0100 Subject: [PATCH 154/217] Add url to reach the view --- bookwyrm/urls.py | 5 +++++ bookwyrm/views/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 514bb7e60..1f62c2be5 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -336,6 +336,11 @@ urlpatterns = [ ), re_path(r"^save-list/(?P\d+)/?$", views.save_list, name="list-save"), re_path(r"^unsave-list/(?P\d+)/?$", views.unsave_list, name="list-unsave"), + re_path( + r"^list/(?P\d+)/embed/(?P[0-9a-f]+)?$", + views.unsafe_embed_list, + name="embed-list", + ), # User books re_path(rf"{USER_PATH}/books/?$", views.Shelf.as_view(), name="user-shelves"), re_path( diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index d79de4248..d363431c0 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -76,7 +76,7 @@ from .inbox import Inbox from .interaction import Favorite, Unfavorite, Boost, Unboost from .isbn import Isbn from .list import Lists, SavedLists, List, Curate, UserLists -from .list import save_list, unsave_list, delete_list +from .list import save_list, unsave_list, delete_list, unsafe_embed_list from .notifications import Notifications from .outbox import Outbox from .reading import create_readthrough, delete_readthrough, delete_progressupdate From 2c7c3fd1c9bee871ff56e5106a2bcf9f04374094 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:08:15 +0100 Subject: [PATCH 155/217] Create a new layout for embedded content --- bookwyrm/templates/embed-layout.html | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 bookwyrm/templates/embed-layout.html diff --git a/bookwyrm/templates/embed-layout.html b/bookwyrm/templates/embed-layout.html new file mode 100644 index 000000000..d9b1198c3 --- /dev/null +++ b/bookwyrm/templates/embed-layout.html @@ -0,0 +1,53 @@ +{% load layout %} +{% load i18n %} +{% load static %} + + + + {% block title %}BookWyrm{% endblock %} - {{ site.name }} + + + + + + + + + + + +
    + + + {{ site.name }} + +
    + +
    + {% block content %} + {% endblock %} +
    + + + +{% block scripts %}{% endblock %} + + From 1b9291616b6046acc1d0dce43dfa3d949c35af81 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:08:47 +0100 Subject: [PATCH 156/217] Add EmbedList view template --- bookwyrm/templates/lists/embed-list.html | 59 ++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 bookwyrm/templates/lists/embed-list.html diff --git a/bookwyrm/templates/lists/embed-list.html b/bookwyrm/templates/lists/embed-list.html new file mode 100644 index 000000000..54dc80ab2 --- /dev/null +++ b/bookwyrm/templates/lists/embed-list.html @@ -0,0 +1,59 @@ +{% extends 'embed-layout.html' %} +{% load i18n %} +{% load bookwyrm_tags %} +{% load bookwyrm_group_tags %} +{% load markdown %} + +{% block title %}{% blocktrans with list_name=list.name owner=list.user.display_name %}{{ list_name }}, a list by {{owner}}{% endblocktrans %}{% endblock title %} + +{% block content %} +
    +

    + {{ list.name }} + {% include 'snippets/privacy-icons.html' with item=list %} +

    +

    + {% include 'lists/created_text.html' with list=list %} + {% blocktrans with site_name=site.name %}on {{ site_name }}{% endblocktrans %} +

    + +
    + {% include 'snippets/trimmed_text.html' with full=list.description %} +
    + +
    + {% if not items.object_list.exists %} +

    {% trans "This list is currently empty" %}

    + {% else %} +
      + {% for item in items %} + {% with book=item.book %} +
    1. +
      + + +
      +

      + {% include 'snippets/book_titleby.html' %} +

      +

      + {% include 'snippets/stars.html' with rating=item.book|rating:request.user %} +

      +
      + {{ book|book_description|to_markdown|default:""|safe|truncatewords_html:20 }} +
      +
      +
      +
    2. + {% endwith %} + {% endfor %} +
    + {% endif %} + {% include "snippets/pagination.html" with page=items %} +
    +
    +{% endblock %} From 306ea962c4700556c05e56c95e82923a93d63662 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:17:21 +0100 Subject: [PATCH 157/217] Add embed URL component to list layout --- bookwyrm/templates/lists/list.html | 7 +++++++ bookwyrm/views/list.py | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/bookwyrm/templates/lists/list.html b/bookwyrm/templates/lists/list.html index 61e31c06e..412ca470f 100644 --- a/bookwyrm/templates/lists/list.html +++ b/bookwyrm/templates/lists/list.html @@ -186,6 +186,13 @@ {% endfor %} {% endif %} {% endif %} +
    +

    + {% trans "Embed this list on a website" %} +

    + +
    +
    {% endblock %} diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index 89e7fa465..82c39f4a5 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -168,6 +168,14 @@ class List(View): ][: 5 - len(suggestions)] page = paginated.get_page(request.GET.get("page")) + + embed_key = str(book_list.embed_key.hex) + embed_url = reverse("embed-list", args=[book_list.id, embed_key]) + embed_url = request.build_absolute_uri(embed_url) + + if request.GET: + embed_url = "%s?%s" % (embed_url, request.GET.urlencode()) + data = { "list": book_list, "items": page, @@ -181,6 +189,7 @@ class List(View): "sort_form": forms.SortListForm( {"direction": direction, "sort_by": sort_by} ), + "embed_url": embed_url, } return TemplateResponse(request, "lists/list.html", data) From b2a274ba41bc6f93a5f45e34a57ab323a2169e6b Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:17:33 +0100 Subject: [PATCH 158/217] Add JS code for copy text component --- bookwyrm/static/js/bookwyrm.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index d656ed183..0816231d6 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -66,6 +66,9 @@ let BookWyrm = new class { document.querySelectorAll('input[type="file"]').forEach( bookwyrm.disableIfTooLarge.bind(bookwyrm) ); + document.querySelectorAll('[data-copytext]').forEach( + bookwyrm.copyText.bind(bookwyrm) + ); }); } @@ -430,4 +433,31 @@ let BookWyrm = new class { parent.appendChild(label) parent.appendChild(input) } + + /** + * Set up a "click-to-copy" component from a textarea element + * with `data-copytext`, `data-copytext-label`, `data-copytext-success` + * attributes. + * + * @param {object} node - DOM node of the text container + * @return {undefined} + */ + + copyText(textareaEl) { + const text = textareaEl.textContent; + + const copyButtonEl = document.createElement('button'); + + copyButtonEl.textContent = textareaEl.dataset.copytextLabel; + copyButtonEl.classList.add("mt-2","button","is-small","is-fullwidth","is-primary","is-light"); + copyButtonEl.addEventListener('click', () => { + navigator.clipboard.writeText(text).then(function() { + textareaEl.classList.add('is-success'); + copyButtonEl.classList.replace('is-primary', 'is-success'); + copyButtonEl.textContent = textareaEl.dataset.copytextSuccess; + }); + }); + + textareaEl.parentNode.appendChild(copyButtonEl) + } }(); From 78a0092f922fd6a3ae5b562e190eb859701d5a63 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 16:17:51 +0100 Subject: [PATCH 159/217] Translate `home page` on main layout --- bookwyrm/templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index f2d04f961..901c417fd 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -34,7 +34,7 @@

    {% endwith %} {% endspaceless %} From b6106691ef85afe7ab15b4f1b239e676503aad9d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 4 Dec 2021 09:57:45 -0800 Subject: [PATCH 170/217] Force dropdown menus to always visible --- bookwyrm/static/css/bookwyrm.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 3d9db3011..4f4d2efc4 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -115,7 +115,7 @@ input[type=file]::file-selector-button:hover { color: #363636; } -details[open] .dropdown-menu { +details .dropdown-menu { display: block !important; } From 5e9e7db9356cbdecc3c302c69eeb2f6723915508 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 19:08:55 +0100 Subject: [PATCH 171/217] Fix preview image text wrap length Closes #1634 --- bookwyrm/preview_images.py | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index 32465d6ed..164ba9e98 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -49,6 +49,25 @@ def get_font(font_name, size=28): return font +def get_wrapped_text(text, font, content_width): + """text wrap length depends on the max width of the content""" + + low = 0 + high = len(text) + + # ideal length is determined via binary search + while low < high: + mid = math.floor(low + high) + wrapped_text = textwrap.fill(text, width=mid) + width = font.getsize_multiline(wrapped_text)[0] + if width < content_width: + low = mid + else: + high = mid - 1 + + return wrapped_text + + def generate_texts_layer(texts, content_width): """Adds text for images""" font_text_zero = get_font("bold", size=20) @@ -63,7 +82,8 @@ def generate_texts_layer(texts, content_width): if "text_zero" in texts and texts["text_zero"]: # Text one (Book title) - text_zero = textwrap.fill(texts["text_zero"], width=72) + text_zero = get_wrapped_text(texts["text_zero"], font_text_zero, content_width) + text_layer_draw.multiline_text( (0, text_y), text_zero, font=font_text_zero, fill=TEXT_COLOR ) @@ -75,7 +95,8 @@ def generate_texts_layer(texts, content_width): if "text_one" in texts and texts["text_one"]: # Text one (Book title) - text_one = textwrap.fill(texts["text_one"], width=28) + text_one = get_wrapped_text(texts["text_one"], font_text_one, content_width) + text_layer_draw.multiline_text( (0, text_y), text_one, font=font_text_one, fill=TEXT_COLOR ) @@ -87,7 +108,8 @@ def generate_texts_layer(texts, content_width): if "text_two" in texts and texts["text_two"]: # Text one (Book subtitle) - text_two = textwrap.fill(texts["text_two"], width=36) + text_two = get_wrapped_text(texts["text_two"], font_text_two, content_width) + text_layer_draw.multiline_text( (0, text_y), text_two, font=font_text_two, fill=TEXT_COLOR ) @@ -99,7 +121,10 @@ def generate_texts_layer(texts, content_width): if "text_three" in texts and texts["text_three"]: # Text three (Book authors) - text_three = textwrap.fill(texts["text_three"], width=36) + text_three = get_wrapped_text( + texts["text_three"], font_text_three, content_width + ) + text_layer_draw.multiline_text( (0, text_y), text_three, font=font_text_three, fill=TEXT_COLOR ) From c813ce1144d31a90d16f556428578f8e63c3f628 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 4 Dec 2021 10:41:42 -0800 Subject: [PATCH 172/217] Creates consistent styling for details element --- bookwyrm/static/css/bookwyrm.css | 13 +++++ bookwyrm/templates/feed/feed.html | 83 ++++++++++++++++--------------- 2 files changed, 57 insertions(+), 39 deletions(-) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 0d280fd53..8f6167b78 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -115,6 +115,19 @@ input[type=file]::file-selector-button:hover { color: #363636; } +summary::marker { + content: none; +} +.detail-pinned-button summary { + position: absolute; + right: 0; +} +.detail-pinned-button form { + float: left; + width: -webkit-fill-available; + margin-top: 1em; +} + /** Shelving ******************************************************************************/ diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 1a2488afe..eda4c0c03 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -6,49 +6,54 @@

    {{ tab.name }}

    -
    - -
    +
    +
    +
    + +
    +
    -{# feed settings #} -
    - - - {{ _("Feed settings") }} - - {% if settings_saved %} - {{ _("Saved!") }} - {% endif %} - - - {% csrf_token %} + {# feed settings #} +
    + + + + {{ _("Feed settings") }} + + {% if settings_saved %} + {{ _("Saved!") }} + {% endif %} + + + {% csrf_token %} -
    -
    -
    - - {% for name, value in feed_status_types_options %} - - {% endfor %} +
    +
    +
    + + {% for name, value in feed_status_types_options %} + + {% endfor %} +
    -
    -
    - -
    - -
    +
    + +
    + +
    +
    {# announcements and system messages #} {% if not activities.number > 1 %} From 5b690532fadea83fcb5ddfcb0db4ee75f439f963 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 4 Dec 2021 19:59:45 +0100 Subject: [PATCH 173/217] Add an AttributeError exception for CI tests --- bookwyrm/preview_images.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py index 164ba9e98..a97ae2d5c 100644 --- a/bookwyrm/preview_images.py +++ b/bookwyrm/preview_images.py @@ -55,15 +55,18 @@ def get_wrapped_text(text, font, content_width): low = 0 high = len(text) - # ideal length is determined via binary search - while low < high: - mid = math.floor(low + high) - wrapped_text = textwrap.fill(text, width=mid) - width = font.getsize_multiline(wrapped_text)[0] - if width < content_width: - low = mid - else: - high = mid - 1 + try: + # ideal length is determined via binary search + while low < high: + mid = math.floor(low + high) + wrapped_text = textwrap.fill(text, width=mid) + width = font.getsize_multiline(wrapped_text)[0] + if width < content_width: + low = mid + else: + high = mid - 1 + except AttributeError: + wrapped_text = text return wrapped_text From 56609bbc2bf0d3b5f13b488815421213fda1a5ca Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 4 Dec 2021 11:18:41 -0800 Subject: [PATCH 174/217] Css linting --- bookwyrm/static/css/bookwyrm.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 8f6167b78..ca164244c 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -118,10 +118,12 @@ input[type=file]::file-selector-button:hover { summary::marker { content: none; } + .detail-pinned-button summary { position: absolute; right: 0; } + .detail-pinned-button form { float: left; width: -webkit-fill-available; From f98fe0348a041c1b230e02a1acee4421211808dc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 4 Dec 2021 11:45:02 -0800 Subject: [PATCH 175/217] Fixes merge error --- bookwyrm/static/css/bookwyrm.css | 1 + 1 file changed, 1 insertion(+) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 145bf439c..7e2b24bc6 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -117,6 +117,7 @@ input[type=file]::file-selector-button:hover { details .dropdown-menu { display: block !important; +} summary::marker { content: none; From 7050013144eb410f098fa0b627c3d34285393663 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 4 Dec 2021 11:51:57 -0800 Subject: [PATCH 176/217] Close menus when the rest of the page is clicked Ce-authored-by: Joachim --- bookwyrm/static/css/bookwyrm.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 7e2b24bc6..0e812e2a3 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -119,6 +119,15 @@ details .dropdown-menu { display: block !important; } +details.dropdown[open] summary.dropdown-trigger::before { + content: ""; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + summary::marker { content: none; } From ba34e11fb01e7253dcf7baf0173dbcdbed5ddf81 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 4 Dec 2021 12:11:29 -0800 Subject: [PATCH 177/217] Fixes auto-closing menu --- bookwyrm/static/js/status_cache.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/static/js/status_cache.js b/bookwyrm/static/js/status_cache.js index 418b7dee2..dbc238c48 100644 --- a/bookwyrm/static/js/status_cache.js +++ b/bookwyrm/static/js/status_cache.js @@ -210,10 +210,10 @@ let StatusCache = new class { .forEach(item => BookWyrm.addRemoveClass(item, "is-hidden", true)); // Close menu - let menu = button.querySelector(".dropdown-trigger[aria-expanded=true]"); + let menu = button.querySelector("details[open]"); if (menu) { - menu.click(); + menu.removeAttribute("open"); } } From 597d537461acdf0b03cbf7ce3e989e94c1306f59 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 4 Dec 2021 13:43:01 -0800 Subject: [PATCH 178/217] Display "saved!" indicator in status form --- bookwyrm/templates/feed/feed.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index eda4c0c03..010ba0f9d 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -26,9 +26,6 @@ {{ _("Feed settings") }} - {% if settings_saved %} - {{ _("Saved!") }} - {% endif %}
    {% csrf_token %} @@ -36,7 +33,12 @@
    - + + + {% if settings_saved %} + {{ _("Saved!") }} + {% endif %} + {% for name, value in feed_status_types_options %}