diff --git a/.env.dev.example b/.env.dev.example index 22e12de1..0a9865cd 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -16,6 +16,7 @@ DEFAULT_LANGUAGE="English" MEDIA_ROOT=images/ +# Database configuration PGPORT=5432 POSTGRES_PASSWORD=securedbypassword123 POSTGRES_USER=fedireads @@ -26,22 +27,31 @@ POSTGRES_HOST=db MAX_STREAM_LENGTH=200 REDIS_ACTIVITY_HOST=redis_activity REDIS_ACTIVITY_PORT=6379 -#REDIS_ACTIVITY_PASSWORD=redispassword345 +REDIS_ACTIVITY_PASSWORD=redispassword345 # Redis as celery broker REDIS_BROKER_PORT=6379 -#REDIS_BROKER_PASSWORD=redispassword123 +REDIS_BROKER_PASSWORD=redispassword123 +# Monitoring for celery FLOWER_PORT=8888 -#FLOWER_USER=mouse -#FLOWER_PASSWORD=changeme +FLOWER_USER=mouse +FLOWER_PASSWORD=changeme +# Email config EMAIL_HOST=smtp.mailgun.org EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here EMAIL_HOST_PASSWORD=emailpassword123 EMAIL_USE_TLS=true EMAIL_USE_SSL=false +EMAIL_SENDER_NAME=admin +# defaults to DOMAIN +EMAIL_SENDER_DOMAIN= + +# Query timeouts +SEARCH_TIMEOUT=15 +QUERY_TIMEOUT=5 # Thumbnails Generation ENABLE_THUMBNAIL_GENERATION=false diff --git a/.env.prod.example b/.env.prod.example index 2e0ced5e..3c935287 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -16,6 +16,7 @@ DEFAULT_LANGUAGE="English" MEDIA_ROOT=images/ +# Database configuration PGPORT=5432 POSTGRES_PASSWORD=securedbypassword123 POSTGRES_USER=fedireads @@ -32,16 +33,25 @@ REDIS_ACTIVITY_PASSWORD=redispassword345 REDIS_BROKER_PORT=6379 REDIS_BROKER_PASSWORD=redispassword123 +# Monitoring for celery FLOWER_PORT=8888 FLOWER_USER=mouse FLOWER_PASSWORD=changeme +# Email config EMAIL_HOST=smtp.mailgun.org EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here EMAIL_HOST_PASSWORD=emailpassword123 EMAIL_USE_TLS=true EMAIL_USE_SSL=false +EMAIL_SENDER_NAME=admin +# defaults to DOMAIN +EMAIL_SENDER_DOMAIN= + +# Query timeouts +SEARCH_TIMEOUT=15 +QUERY_TIMEOUT=5 # Thumbnails Generation ENABLE_THUMBNAIL_GENERATION=false diff --git a/.github/workflows/django-tests.yml b/.github/workflows/django-tests.yml index 03875193..00e08dad 100644 --- a/.github/workflows/django-tests.yml +++ b/.github/workflows/django-tests.yml @@ -46,6 +46,8 @@ jobs: POSTGRES_HOST: 127.0.0.1 CELERY_BROKER: "" REDIS_BROKER_PORT: 6379 + REDIS_BROKER_PASSWORD: beep + USE_DUMMY_CACHE: true FLOWER_PORT: 8888 EMAIL_HOST: "smtp.mailgun.org" EMAIL_PORT: 587 diff --git a/.stylelintrc.js b/.stylelintrc.js index eadc4a89..68c68f89 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -12,6 +12,9 @@ module.exports = { "custom-properties", "declarations" ], - "indentation": 4 + "indentation": 4, + "property-no-vendor-prefix": null, + "color-function-notation": null, + "declaration-block-no-redundant-longhand-properties": null, } }; diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index 20a17526..5ed57df1 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -35,7 +35,7 @@ class AbstractMinimalConnector(ABC): for field in self_fields: setattr(self, field, getattr(info, field)) - def search(self, query, min_confidence=None, timeout=5): + def search(self, query, min_confidence=None, timeout=settings.QUERY_TIMEOUT): """free text search""" params = {} if min_confidence: @@ -52,12 +52,13 @@ class AbstractMinimalConnector(ABC): results.append(self.format_search_result(doc)) return results - def isbn_search(self, query): + def isbn_search(self, query, timeout=settings.QUERY_TIMEOUT): """isbn search""" params = {} data = self.get_search_data( f"{self.isbn_search_url}{query}", params=params, + timeout=timeout, ) results = [] diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 45530cd6..3bdd5cb4 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -11,6 +11,7 @@ from django.db.models import signals from requests import HTTPError from bookwyrm import book_search, models +from bookwyrm.settings import SEARCH_TIMEOUT from bookwyrm.tasks import app logger = logging.getLogger(__name__) @@ -30,7 +31,6 @@ def search(query, min_confidence=0.1, return_first=False): isbn = re.sub(r"[\W_]", "", query) maybe_isbn = len(isbn) in [10, 13] # ISBN10 or ISBN13 - timeout = 15 start_time = datetime.now() for connector in get_connectors(): result_set = None @@ -62,7 +62,7 @@ def search(query, min_confidence=0.1, return_first=False): "results": result_set, } ) - if (datetime.now() - start_time).seconds >= timeout: + if (datetime.now() - start_time).seconds >= SEARCH_TIMEOUT: break if return_first: diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py index 08fd9ef8..efef1263 100644 --- a/bookwyrm/emailing.py +++ b/bookwyrm/emailing.py @@ -69,7 +69,7 @@ def format_email(email_name, data): def send_email(recipient, subject, html_content, text_content): """use a task to send the email""" email = EmailMultiAlternatives( - subject, text_content, settings.DEFAULT_FROM_EMAIL, [recipient] + subject, text_content, settings.EMAIL_SENDER, [recipient] ) email.attach_alternative(html_content, "text/html") email.send() diff --git a/bookwyrm/models/author.py b/bookwyrm/models/author.py index 5cc11afd..5edac57d 100644 --- a/bookwyrm/models/author.py +++ b/bookwyrm/models/author.py @@ -1,6 +1,8 @@ """ database schema for info about authors """ import re from django.contrib.postgres.indexes import GinIndex +from django.core.cache import cache +from django.core.cache.utils import make_template_fragment_key from django.db import models from bookwyrm import activitypub @@ -34,6 +36,17 @@ class Author(BookDataModel): ) bio = fields.HtmlField(null=True, blank=True) + def save(self, *args, **kwargs): + """clear related template caches""" + # clear template caches + if self.id: + cache_keys = [ + make_template_fragment_key("titleby", [book]) + for book in self.book_set.values_list("id", flat=True) + ] + cache.delete_many(cache_keys) + return super().save(*args, **kwargs) + @property def isni_link(self): """generate the url from the isni id""" diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index 0a551bf2..a9dd9508 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -3,6 +3,8 @@ import re from django.contrib.postgres.search import SearchVectorField from django.contrib.postgres.indexes import GinIndex +from django.core.cache import cache +from django.core.cache.utils import make_template_fragment_key from django.db import models, transaction from django.db.models import Prefetch from django.dispatch import receiver @@ -185,6 +187,11 @@ class Book(BookDataModel): """can't be abstract for query reasons, but you shouldn't USE it""" if not isinstance(self, Edition) and not isinstance(self, Work): raise ValueError("Books should be added as Editions or Works") + + # clear template caches + cache_key = make_template_fragment_key("titleby", [self.id]) + cache.delete(cache_key) + return super().save(*args, **kwargs) def get_remote_id(self): diff --git a/bookwyrm/models/relationship.py b/bookwyrm/models/relationship.py index fc7a9df8..03417454 100644 --- a/bookwyrm/models/relationship.py +++ b/bookwyrm/models/relationship.py @@ -1,5 +1,7 @@ """ defines relationships between users """ from django.apps import apps +from django.core.cache import cache +from django.core.cache.utils import make_template_fragment_key from django.db import models, transaction, IntegrityError from django.db.models import Q @@ -36,6 +38,20 @@ class UserRelationship(BookWyrmModel): """the remote user needs to recieve direct broadcasts""" return [u for u in [self.user_subject, self.user_object] if not u.local] + def save(self, *args, **kwargs): + """clear the template cache""" + # invalidate the template cache + cache_keys = [ + make_template_fragment_key( + "follow_button", [self.user_subject.id, self.user_object.id] + ), + make_template_fragment_key( + "follow_button", [self.user_object.id, self.user_subject.id] + ), + ] + cache.delete_many(cache_keys) + super().save(*args, **kwargs) + class Meta: """relationships should be unique""" diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index c7c0a425..ee138d97 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -82,6 +82,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): if not self.reply_parent: self.thread_id = self.id + super().save(broadcast=False, update_fields=["thread_id"]) def delete(self, *args, **kwargs): # pylint: disable=unused-argument diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index 78f373a2..595868ff 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -5,7 +5,10 @@ import redis from bookwyrm import settings r = redis.Redis( - host=settings.REDIS_ACTIVITY_HOST, port=settings.REDIS_ACTIVITY_PORT, db=0 + host=settings.REDIS_ACTIVITY_HOST, + port=settings.REDIS_ACTIVITY_PORT, + password=settings.REDIS_ACTIVITY_PASSWORD, + db=0, ) diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index f2068a16..5920ed80 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -24,7 +24,9 @@ EMAIL_HOST_USER = env("EMAIL_HOST_USER") EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD") EMAIL_USE_TLS = env.bool("EMAIL_USE_TLS", True) EMAIL_USE_SSL = env.bool("EMAIL_USE_SSL", False) -DEFAULT_FROM_EMAIL = f"admin@{DOMAIN}" +EMAIL_SENDER_NAME = env("EMAIL_SENDER_NAME", "admin") +EMAIL_SENDER_DOMAIN = env("EMAIL_SENDER_NAME", DOMAIN) +EMAIL_SENDER = f"{EMAIL_SENDER_NAME}@{EMAIL_SENDER_DOMAIN}" # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -119,6 +121,34 @@ STREAMS = [ {"key": "books", "name": _("Books Timeline"), "shortname": _("Books")}, ] +# Search configuration +# total time in seconds that the instance will spend searching connectors +SEARCH_TIMEOUT = int(env("SEARCH_TIMEOUT", 15)) +# timeout for a query to an individual connector +QUERY_TIMEOUT = int(env("QUERY_TIMEOUT", 5)) + +# Redis cache backend +if env("USE_DUMMY_CACHE", False): + CACHES = { + "default": { + "BACKEND": "django.core.cache.backends.dummy.DummyCache", + } + } +else: + # pylint: disable=line-too-long + CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": f"redis://:{REDIS_ACTIVITY_PASSWORD}@{REDIS_ACTIVITY_HOST}:{REDIS_ACTIVITY_PORT}/0", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + }, + } + } + + SESSION_ENGINE = "django.contrib.sessions.backends.cache" + SESSION_CACHE_ALIAS = "default" + # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 15324a14..4d960734 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -183,7 +183,7 @@ button .button-invisible-overlay { align-items: center; flex-direction: column; justify-content: center; - background: rgba(0, 0, 0, 0.66); + background: rgba(0, 0, 0, 66%); color: white; opacity: 0; transition: opacity 0.2s ease; @@ -198,7 +198,7 @@ button:focus-visible .button-invisible-overlay { /** File input styles ******************************************************************************/ -input[type=file]::file-selector-button { +input[type="file"]::file-selector-button { -moz-appearance: none; -webkit-appearance: none; background-color: #fff; @@ -219,7 +219,7 @@ input[type=file]::file-selector-button { white-space: nowrap; } -input[type=file]::file-selector-button:hover { +input[type="file"]::file-selector-button:hover { border-color: #b5b5b5; color: #363636; } @@ -279,7 +279,7 @@ details.dropdown .dropdown-menu a:focus-visible { @media only screen and (max-width: 768px) { details.dropdown[open] summary.dropdown-trigger::before { - background-color: rgba(0, 0, 0, 0.5); + background-color: rgba(0, 0, 0, 50%); z-index: 30; } @@ -305,14 +305,14 @@ details.dropdown .dropdown-menu a:focus-visible { ******************************************************************************/ details.details-panel { - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 10%); transition: box-shadow 0.2s ease; padding: 0.75rem; } details[open].details-panel, details.details-panel:hover { - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 20%); } details.details-panel summary { @@ -333,7 +333,7 @@ details[open].details-panel summary .details-close { @media only screen and (min-width: 769px) { .details-panel .filters-field:not(:last-child) { - border-right: 1px solid rgba(0, 0, 0, 0.1); + border-right: 1px solid rgba(0, 0, 0, 10%); margin-top: 0.75rem; margin-bottom: 0.75rem; padding-top: 0.25rem; @@ -347,7 +347,7 @@ details[open].details-panel summary .details-close { /** @todo Replace icons with SVG symbols. @see https://www.youtube.com/watch?v=9xXBYcWgCHA */ .shelf-option:disabled > *::after { - font-family: "icomoon"; /* stylelint-disable font-family-no-missing-generic-family-keyword */ + font-family: icomoon; /* stylelint-disable font-family-no-missing-generic-family-keyword */ content: "\e919"; /* icon-check */ margin-left: 0.5em; } @@ -355,14 +355,14 @@ details[open].details-panel summary .details-close { /** Toggles ******************************************************************************/ -.toggle-button[aria-pressed=true], -.toggle-button[aria-pressed=true]:hover { - background-color: hsl(171, 100%, 41%); +.toggle-button[aria-pressed="true"], +.toggle-button[aria-pressed="true"]:hover { + background-color: hsl(171deg, 100%, 41%); color: white; } -.hide-active[aria-pressed=true], -.hide-inactive[aria-pressed=false] { +.hide-active[aria-pressed="true"], +.hide-inactive[aria-pressed="false"] { display: none; } @@ -419,36 +419,36 @@ details[open].details-panel summary .details-close { /* All stars are visually filled by default. */ .form-rate-stars .icon::before { - content: '\e9d9'; /* icon-star-full */ + content: "\e9d9"; /* icon-star-full */ } /* Icons directly following half star inputs are marked as half */ .form-rate-stars input.half:checked ~ .icon::before { - content: '\e9d8'; /* icon-star-half */ + content: "\e9d8"; /* icon-star-half */ } /* stylelint-disable no-descending-specificity */ .form-rate-stars input.half:checked + input + .icon:hover::before { - content: '\e9d8' !important; /* icon-star-half */ + content: "\e9d8" !important; /* icon-star-half */ } /* Icons directly following half check inputs that follow the checked input are emptied. */ .form-rate-stars input.half:checked + input + .icon ~ .icon::before { - content: '\e9d7'; /* icon-star-empty */ + content: "\e9d7"; /* icon-star-empty */ } /* Icons directly following inputs that follow the checked input are emptied. */ .form-rate-stars input:checked ~ input + .icon::before { - content: '\e9d7'; /* icon-star-empty */ + content: "\e9d7"; /* icon-star-empty */ } /* When a label is hovered, repeat the fill-all-then-empty-following pattern. */ .form-rate-stars:hover .icon.icon::before { - content: '\e9d9' !important; /* icon-star-full */ + content: "\e9d9" !important; /* icon-star-full */ } .form-rate-stars .icon:hover ~ .icon::before { - content: '\e9d7' !important; /* icon-star-empty */ + content: "\e9d7" !important; /* icon-star-empty */ } /** Book covers @@ -556,7 +556,7 @@ details[open].details-panel summary .details-close { .quote > blockquote::before, .quote > blockquote::after { - font-family: 'icomoon'; + font-family: icomoon; position: absolute; } diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index 5769ca8b..b30e8412 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -29,6 +29,7 @@ class SuggestedUsers(RedisStore): def get_counts_from_rank(self, rank): # pylint: disable=no-self-use """calculate mutuals count and shared books count from rank""" + # pylint: disable=c-extension-no-member return { "mutuals": math.floor(rank), # "shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1, @@ -94,7 +95,7 @@ class SuggestedUsers(RedisStore): ).annotate(mutuals=Case(*annotations, output_field=IntegerField(), default=0)) if local: users = users.filter(local=True) - return users[:5] + return users.order_by("-mutuals")[:5] def get_annotated_users(viewer, *args, **kwargs): @@ -112,16 +113,17 @@ def get_annotated_users(viewer, *args, **kwargs): ), distinct=True, ), - # shared_books=Count( - # "shelfbook", - # filter=Q( - # ~Q(id=viewer.id), - # shelfbook__book__parent_work__in=[ - # s.book.parent_work for s in viewer.shelfbook_set.all() - # ], - # ), - # distinct=True, - # ), + # pylint: disable=line-too-long + # shared_books=Count( + # "shelfbook", + # filter=Q( + # ~Q(id=viewer.id), + # shelfbook__book__parent_work__in=[ + # s.book.parent_work for s in viewer.shelfbook_set.all() + # ], + # ), + # distinct=True, + # ), ) ) diff --git a/bookwyrm/templates/annual_summary/layout.html b/bookwyrm/templates/annual_summary/layout.html index ab25458c..c333c26d 100644 --- a/bookwyrm/templates/annual_summary/layout.html +++ b/bookwyrm/templates/annual_summary/layout.html @@ -109,7 +109,7 @@ {% if not books %} -

{% blocktrans %}Sadly {{ display_name }} didn’t finish any book in {{ year }}{% endblocktrans %}

+

{% blocktrans %}Sadly {{ display_name }} didn’t finish any books in {{ year }}{% endblocktrans %}

{% else %}
diff --git a/bookwyrm/templates/directory/sort_filter.html b/bookwyrm/templates/directory/sort_filter.html index c7c19f6f..34436601 100644 --- a/bookwyrm/templates/directory/sort_filter.html +++ b/bookwyrm/templates/directory/sort_filter.html @@ -3,10 +3,12 @@ {% block filter %} -
- +
+
+ +
{% endblock %} diff --git a/bookwyrm/templates/feed/layout.html b/bookwyrm/templates/feed/layout.html index 6e7ec849..5697f266 100644 --- a/bookwyrm/templates/feed/layout.html +++ b/bookwyrm/templates/feed/layout.html @@ -8,82 +8,7 @@
{% if user.is_authenticated %}
-
-

{% trans "Your Books" %}

- {% if not suggested_books %} -

{% trans "There are no books here right now! Try searching for a book to get started" %}

- {% else %} - {% with active_book=request.GET.book %} -
-
-
    - {% for shelf in suggested_books %} - {% if shelf.books %} - {% with shelf_counter=forloop.counter %} -
  • -

    - {% 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 %} -

    -
    - -
    -
  • - {% endwith %} - {% endif %} - {% endfor %} -
-
- {% for shelf in suggested_books %} - {% with shelf_counter=forloop.counter %} - {% for book in shelf.books %} -
- -
-
-
-

{% include 'snippets/book_titleby.html' with book=book %}

- {% include 'snippets/shelve_button/shelve_button.html' with book=book %} -
-
-
- {% trans "Close" as button_text %} - {% include 'snippets/toggle/toggle_button.html' with label=button_text controls_text="book" controls_uid=book.id class="delete" nonbutton=True pressed=True %} -
-
-
- {% include 'snippets/create_status.html' with book=book %} -
-
- {% endfor %} - {% endwith %} - {% endfor %} -
- {% endwith %} - {% endif %} -
- + {% include "feed/suggested_books.html" %} {% if goal %}
diff --git a/bookwyrm/templates/feed/suggested_books.html b/bookwyrm/templates/feed/suggested_books.html new file mode 100644 index 00000000..899767d1 --- /dev/null +++ b/bookwyrm/templates/feed/suggested_books.html @@ -0,0 +1,79 @@ +{% load i18n %} +{% load bookwyrm_tags %} + +{% suggested_books as suggested_books %} +
+

{% trans "Your Books" %}

+ {% if not suggested_books %} +

{% trans "There are no books here right now! Try searching for a book to get started" %}

+ {% else %} + {% with active_book=request.GET.book %} +
+
+
    + {% for shelf in suggested_books %} + {% if shelf.books %} + {% with shelf_counter=forloop.counter %} +
  • +

    + {% 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 %} +

    +
    + +
    +
  • + {% endwith %} + {% endif %} + {% endfor %} +
+
+ {% for shelf in suggested_books %} + {% with shelf_counter=forloop.counter %} + {% for book in shelf.books %} +
+ +
+
+
+

{% include 'snippets/book_titleby.html' with book=book %}

+ {% include 'snippets/shelve_button/shelve_button.html' with book=book %} +
+
+
+ {% trans "Close" as button_text %} + {% include 'snippets/toggle/toggle_button.html' with label=button_text controls_text="book" controls_uid=book.id class="delete" nonbutton=True pressed=True %} +
+
+
+ {% include 'snippets/create_status.html' with book=book %} +
+
+ {% endfor %} + {% endwith %} + {% endfor %} +
+ {% endwith %} + {% endif %} +
diff --git a/bookwyrm/templates/landing/landing.html b/bookwyrm/templates/landing/landing.html index d13cd582..759e8c61 100644 --- a/bookwyrm/templates/landing/landing.html +++ b/bookwyrm/templates/landing/landing.html @@ -1,11 +1,13 @@ {% extends 'landing/layout.html' %} {% load i18n %} +{% load cache %} {% block panel %}

{% trans "Recent Books" %}

+{% cache 60 * 60 %}
@@ -46,5 +48,5 @@
- +{% endcache %} {% endblock %} diff --git a/bookwyrm/templates/settings/users/server_filter.html b/bookwyrm/templates/settings/users/server_filter.html index 2a4b89fd..5879f748 100644 --- a/bookwyrm/templates/settings/users/server_filter.html +++ b/bookwyrm/templates/settings/users/server_filter.html @@ -3,5 +3,7 @@ {% block filter %} - +
+ +
{% endblock %} diff --git a/bookwyrm/templates/settings/users/username_filter.html b/bookwyrm/templates/settings/users/username_filter.html index d7da033a..343e61c8 100644 --- a/bookwyrm/templates/settings/users/username_filter.html +++ b/bookwyrm/templates/settings/users/username_filter.html @@ -3,6 +3,7 @@ {% block filter %} - +
+ +
{% endblock %} - diff --git a/bookwyrm/templates/snippets/book_titleby.html b/bookwyrm/templates/snippets/book_titleby.html index 6dbaeb26..5e35e36a 100644 --- a/bookwyrm/templates/snippets/book_titleby.html +++ b/bookwyrm/templates/snippets/book_titleby.html @@ -1,7 +1,11 @@ {% load i18n %} {% load utilities %} +{% load cache %} {% spaceless %} +{# 6 month cache #} +{% cache 15552000 titleby book.id %} + {% if book.authors.exists %} {% blocktrans trimmed with path=book.local_path title=book|book_title %} {{ title }} by @@ -10,4 +14,6 @@ {% else %} {{ book|book_title }} {% endif %} + +{% endcache %} {% endspaceless %} diff --git a/bookwyrm/templates/snippets/follow_button.html b/bookwyrm/templates/snippets/follow_button.html index 530322b9..f7025bba 100644 --- a/bookwyrm/templates/snippets/follow_button.html +++ b/bookwyrm/templates/snippets/follow_button.html @@ -1,4 +1,5 @@ {% load i18n %} + {% if request.user == user or not request.user.is_authenticated %} {% elif user in request.user.blocks.all %} {% include 'snippets/block_button.html' with blocks=True %} diff --git a/bookwyrm/templates/snippets/status/headers/generatednote.html b/bookwyrm/templates/snippets/status/headers/generatednote.html index cc684a5f..7fc635ab 100644 --- a/bookwyrm/templates/snippets/status/headers/generatednote.html +++ b/bookwyrm/templates/snippets/status/headers/generatednote.html @@ -1,3 +1,7 @@ +{% load cache %} + +{# Three day cache #} +{% cache 259200 generated_note_header status.id %} {% if status.content == 'wants to read' %} {% include 'snippets/status/headers/to_read.html' with book=status.mention_books.first %} {% elif status.content == 'finished reading' %} @@ -7,3 +11,4 @@ {% else %} {{ status.content }} {% endif %} +{% endcache %} diff --git a/bookwyrm/templates/snippets/status/layout.html b/bookwyrm/templates/snippets/status/layout.html index 93620a08..5cbcef20 100644 --- a/bookwyrm/templates/snippets/status/layout.html +++ b/bookwyrm/templates/snippets/status/layout.html @@ -30,38 +30,39 @@ {# nothing here #} {% elif request.user.is_authenticated %} - - - -{% if not moderation_mode %} - -{% endif %} + + + + {% if not moderation_mode %} + + {% endif %} {% else %} - {% endif %} {% endblock %} diff --git a/bookwyrm/templates/snippets/status/status_options.html b/bookwyrm/templates/snippets/status/status_options.html index 854d4779..fdf8ac14 100644 --- a/bookwyrm/templates/snippets/status/status_options.html +++ b/bookwyrm/templates/snippets/status/status_options.html @@ -20,17 +20,21 @@ {% if status.status_type != 'GeneratedNote' and status.status_type != 'Rating' %} {% endif %} {% else %} {# things you can do to other people's statuses #}