diff --git a/bookwyrm/importers/librarything_import.py b/bookwyrm/importers/librarything_import.py index 1b61a6f1..37730dee 100644 --- a/bookwyrm/importers/librarything_import.py +++ b/bookwyrm/importers/librarything_import.py @@ -14,7 +14,8 @@ class LibrarythingImporter(Importer): """use the dataclass to create the formatted row of data""" remove_brackets = lambda v: re.sub(r"\[|\]", "", v) if v else None normalized = {k: remove_brackets(entry.get(v)) for k, v in mappings.items()} - isbn_13 = normalized["isbn_13"].split(", ") + isbn_13 = normalized.get("isbn_13") + isbn_13 = isbn_13.split(", ") if isbn_13 else [] normalized["isbn_13"] = isbn_13[1] if len(isbn_13) > 0 else None return normalized diff --git a/bookwyrm/models/base_model.py b/bookwyrm/models/base_model.py index f62678f7..f8d3b781 100644 --- a/bookwyrm/models/base_model.py +++ b/bookwyrm/models/base_model.py @@ -84,6 +84,7 @@ class BookWyrmModel(models.Model): # you can see groups of which you are a member if ( hasattr(self, "memberships") + and viewer.is_authenticated and self.memberships.filter(user=viewer).exists() ): return diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index e95ff96e..f8acca28 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -14,7 +14,7 @@ VERSION = "0.1.0" PAGE_LENGTH = env("PAGE_LENGTH", 15) DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English") -JS_CACHE = "3891b373" +JS_CACHE = "2d3181e1" # email EMAIL_BACKEND = env("EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend") diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css index 4d9aabb4..f8d3b531 100644 --- a/bookwyrm/static/css/bookwyrm.css +++ b/bookwyrm/static/css/bookwyrm.css @@ -8,6 +8,41 @@ body { flex-direction: column; } +button { + border: none; + margin: 0; + padding: 0; + width: auto; + overflow: visible; + background: transparent; + + /* inherit font, color & alignment from ancestor */ + color: inherit; + font: inherit; + text-align: inherit; + + /* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */ + line-height: normal; + + /* Corrects font smoothing for webkit */ + -webkit-font-smoothing: inherit; + -moz-osx-font-smoothing: inherit; + + /* Corrects inability to style clickable `input` types in iOS */ + -webkit-appearance: none; +} + +button::-moz-focus-inner { + /* Remove excess padding and border in Firefox 4+ */ + border: 0; + padding: 0; +} + +/* Better accessibility for keyboard users */ +*:focus-visible { + outline-style: auto !important; +} + .image { overflow: hidden; } @@ -29,10 +64,30 @@ body { overflow-x: auto; } +/* stylelint-disable no-descending-specificity */ +.modal-card:focus { + outline-style: auto; +} + +.modal-card:focus:not(:focus-visible) { + outline-style: initial; +} + +.modal-card:focus-visible { + outline-style: auto; +} +/* stylelint-enable no-descending-specificity */ + .modal-card.is-fullwidth { min-width: 75% !important; } +@media only screen and (min-width: 769px) { + .modal-card.is-thin { + width: 350px !important; + } +} + .modal-card-body { max-height: 70vh; } @@ -612,17 +667,16 @@ ol.ordered-list li::before { .books-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(10em, 1fr)); - gap: 1.5rem; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; align-items: end; - justify-items: center; + justify-items: stretch; } .books-grid > .is-big { grid-column: span 2; grid-row: span 2; justify-self: stretch; - padding: 1.5rem 1.5rem 0; } .books-grid .book-cover { @@ -638,6 +692,17 @@ ol.ordered-list li::before { min-height: calc(2 * var(--height-basis)); } +@media only screen and (min-width: 769px) { + .books-grid { + gap: 1.5rem; + grid-template-columns: repeat(auto-fit, minmax(10em, 1fr)); + } + + .books-grid > .is-big { + padding: 1.5rem 1.5rem 0; + } +} + /* Copy ******************************************************************************/ diff --git a/bookwyrm/static/js/bookwyrm.js b/bookwyrm/static/js/bookwyrm.js index 9af6132b..6d21c207 100644 --- a/bookwyrm/static/js/bookwyrm.js +++ b/bookwyrm/static/js/bookwyrm.js @@ -34,6 +34,10 @@ let BookWyrm = new (class { .querySelectorAll('input[type="file"]') .forEach((node) => node.addEventListener("change", this.disableIfTooLarge.bind(this))); + document + .querySelectorAll("button[data-modal-open]") + .forEach((node) => node.addEventListener("click", this.handleModalButton.bind(this))); + document .querySelectorAll("[data-duplicate]") .forEach((node) => node.addEventListener("click", this.duplicateInput.bind(this))); @@ -400,6 +404,93 @@ let BookWyrm = new (class { } } + /** + * Handle the modal component. + * + * @param {Event} event - Event fired by an element + * with the `data-modal-open` attribute + * pointing to a modal by its id. + * @return {undefined} + * + * See https://github.com/bookwyrm-social/bookwyrm/pull/1633 + * for information about using the modal. + */ + handleModalButton(event) { + const modalButton = event.currentTarget; + const targetModalId = modalButton.dataset.modalOpen; + const htmlElement = document.querySelector("html"); + const modal = document.getElementById(targetModalId); + + if (!modal) { + return; + } + + // Helper functions + function handleModalOpen(modalElement) { + htmlElement.classList.add("is-clipped"); + modalElement.classList.add("is-active"); + modalElement.getElementsByClassName("modal-card")[0].focus(); + + const closeButtons = modalElement.querySelectorAll("[data-modal-close]"); + + closeButtons.forEach((button) => { + button.addEventListener("click", function () { + handleModalClose(modalElement); + }); + }); + + document.addEventListener("keydown", function (event) { + if (event.key === "Escape") { + handleModalClose(modalElement); + } + }); + + modalElement.addEventListener("keydown", handleFocusTrap); + } + + function handleModalClose(modalElement) { + modalElement.removeEventListener("keydown", handleFocusTrap); + htmlElement.classList.remove("is-clipped"); + modalElement.classList.remove("is-active"); + modalButton.focus(); + } + + function handleFocusTrap(event) { + if (event.key !== "Tab") { + return; + } + + const focusableEls = event.currentTarget.querySelectorAll( + [ + "a[href]:not([disabled])", + "button:not([disabled])", + "textarea:not([disabled])", + 'input:not([type="hidden"]):not([disabled])', + "select:not([disabled])", + "details:not([disabled])", + '[tabindex]:not([tabindex="-1"]):not([disabled])', + ].join(",") + ); + const firstFocusableEl = focusableEls[0]; + const lastFocusableEl = focusableEls[focusableEls.length - 1]; + + if (event.shiftKey) { + /* Shift + tab */ if (document.activeElement === firstFocusableEl) { + lastFocusableEl.focus(); + event.preventDefault(); + } + } /* Tab */ else { + if (document.activeElement === lastFocusableEl) { + firstFocusableEl.focus(); + event.preventDefault(); + } + } + } + + // Open modal + handleModalOpen(modal); + } + /** * Display pop up window. * diff --git a/bookwyrm/templates/annual_summary/layout.html b/bookwyrm/templates/annual_summary/layout.html index ac418d70..6a4ec574 100644 --- a/bookwyrm/templates/annual_summary/layout.html +++ b/bookwyrm/templates/annual_summary/layout.html @@ -1,6 +1,7 @@ {% extends 'layout.html' %} {% load i18n %} {% load static %} +{% load humanize %} {% block title %}{% blocktrans %}{{ year }} in the books{% endblocktrans %}{% endblock %} @@ -57,7 +58,15 @@ {% if year_key %}
- +
{% endif %} @@ -106,12 +115,16 @@

- {% blocktrans %}In {{ year }}, {{ display_name }} read {{ books_total }} books
for a total of {{ pages_total }} pages!{% endblocktrans %} + {% blocktrans trimmed count counter=books_total with pages_total=pages_total|intcomma %} + In {{ year }}, {{ display_name }} read {{ books_total }} book
for a total of {{ pages_total }} pages! + {% plural %} + In {{ year }}, {{ display_name }} read {{ books_total }} books
for a total of {{ pages_total }} pages! + {% endblocktrans %}

{% trans "That’s great!" %}

- {% blocktrans %}That makes an average of {{ pages_average }} pages per book.{% endblocktrans %} + {% blocktrans with pages=pages_average|intcomma %}That makes an average of {{ pages }} pages per book.{% endblocktrans %}

{% if no_page_number %} @@ -127,9 +140,9 @@
{% if book_pages_lowest and book_pages_highest %} -
+
{% trans "Their shortest read this year…" %} @@ -150,7 +163,7 @@

{% trans "…and the longest" %} @@ -183,13 +196,17 @@

- {% blocktrans %}{{ display_name }} left {{ ratings_total }} ratings,
their average rating is {{ rating_average }}{% endblocktrans %} + {% blocktrans trimmed count counter=ratings_total %} + {{ display_name }} left {{ ratings_total }} rating,
their average rating is {{ rating_average }} + {% plural %} + {{ display_name }} left {{ ratings_total }} ratings,
their average rating is {{ rating_average }} + {% endblocktrans %}

-
- {% include 'snippets/book_cover.html' with book=book_rating_highest.book cover_class='is-w-auto-tablet is-h-l-mobile' %} + {% if book_rating_highest %}
@@ -223,7 +240,7 @@

- {% blocktrans %}All the books {{ display_name }} read in 2021{% endblocktrans %} + {% blocktrans %}All the books {{ display_name }} read in {{ year }}{% endblocktrans %}

@@ -234,14 +251,14 @@ {% for book in books %} {% if book.id in best_ratings_books_ids %} - {% include 'snippets/book_cover.html' with book=book cover_class='is-w-auto' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-w-auto' size='xxlarge' %} {{ book.title }} {% else %} - {% include 'snippets/book_cover.html' with book=book cover_class='is-w-auto' %} + {% include 'snippets/book_cover.html' with book=book cover_class='is-w-auto' size='xlarge' %} {{ book.title }} diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index f25ec869..45d8f1ae 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -73,7 +73,7 @@ {% endif %} {% if annual_summary_year and tab.key == 'home' %} -
+
{% include 'feed/summary_card.html' with year=annual_summary_year %}
diff --git a/bookwyrm/templates/feed/summary_card.html b/bookwyrm/templates/feed/summary_card.html index a5bc4643..02718cdd 100644 --- a/bookwyrm/templates/feed/summary_card.html +++ b/bookwyrm/templates/feed/summary_card.html @@ -7,6 +7,13 @@ {% blocktrans %}{{ year }} in the books{% endblocktrans %} + +
+ {% trans "Dismiss message" as button_text %} + +
{% endblock %} {% block card-content %} diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index d7710a2a..43e8eb22 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -38,7 +38,7 @@
-