Skip to content

feat(sidebar): consolidate book page CTA card — Borrow + Buy + toast#12867

Open
mekarpeles wants to merge 30 commits into
masterfrom
12826/consolidate-sidebar-cta
Open

feat(sidebar): consolidate book page CTA card — Borrow + Buy + toast#12867
mekarpeles wants to merge 30 commits into
masterfrom
12826/consolidate-sidebar-cta

Conversation

@mekarpeles
Copy link
Copy Markdown
Member

Closes #12826

Summary

  • Consolidate left sidebar: removes the separate "Buy this book" / WorldCat vendor card. WorldCat moves into the Borrow dropdown; affiliate links move into a new Buy <ol-popover> — one unified CTA card.
  • "Locate" suppressed on non-book-page views (carousels, search results, editions table, reading log): shows NotInLibrary instead
  • Book page unavailable state: primary button becomes secondary grey "Check Worldcat" (has OCLC/ISBN) or "Not Available" (neither); Buy button becomes primary blue in this state
  • Borrow button gets book-open icon; Buy button gets cart icon; <ol-popover> for Buy dropdown
  • "Preview" → "Search Inside Preview" with magnifying glass icon
  • Dismissible blue toast banner when book is not available on OL, linking to #related-work-carousel
  • Remove dead action=locate → WorldCat redirect from borrow.py
  • Affiliate commission disclaimer preserved inside Buy popover content

Button state matrix

Availability state Borrow/Read button Buy button
Read or Borrow available Blue primary Grey secondary
Locate only + OCLC/ISBN present Grey secondary "Check Worldcat" Blue primary
No OCLC and no ISBN Grey secondary "Not Available" Grey secondary

Files Changed (sidebar work)

File Change
openlibrary/macros/LoanStatus.html Add worldcat_url param; suppress Locate on non-book-page views; pass URL to ReadButton and LocateButton
openlibrary/macros/LocateButton.html Rewrite as secondary "Check Worldcat" or "Not Available"
openlibrary/macros/ReadButton.html Replace edition_key with worldcat_url; add book-open icon; WorldCat in dropdown
openlibrary/macros/databarWork.html Remove desktop-vendor panel; add Buy <ol-popover> with affiliate links
openlibrary/macros/BookPreview.html Rename to "Search Inside Preview" with search icon
openlibrary/templates/type/edition/view.html Compute worldcat_url; remove mobile-vendor panel; add unavailability toast
openlibrary/plugins/upstream/borrow.py Remove dead action=locate redirect
static/css/components/read-panel.css Add book-open and cart icon mask classes; buy-popover styles; switch Preview icon
static/images/icons/icon_cart.svg New shopping cart icon

Python 3.14 compatibility fixes (pre-existing regression from #12643)

Docker testing on Python 3.12 was blocked by multiple incompatibilities introduced by the Python 3.14 migration in commit 3c3247c. This PR also fixes those to get the dev environment running:

  • Parenthesize except A, B: tuples (Python 3 syntax) across 20+ files
  • Add from __future__ import annotations to 50+ files with TYPE_CHECKING-only runtime annotations
  • Fix warnings.deprecated fallback shim for Python 3.12 (API added in 3.13)
  • Fix @deprecated class decorator shim to pass classes through unchanged
  • Rewrite multi-line Templetor $ expressions as single lines (parser limitation)
  • Fix stylelint violation: currentColorvar(--white) for icon mask colors

Testing

  • Docker HTTP 200 confirmed
  • CSS webpack compile: 0 errors
  • make test: 3912 passed, 18 skipped, 2 pre-existing Solr failures (unrelated — itertools.batched(strict=False) Python 3.13+ API from Update Python #12643)
  • Template validation tests: all pass
  • Pre-commit: ruff, codespell, trailing-whitespace, stylelint all pass; mypy/generate-pot require Docker (expected)
  • Browser verification: dev DB has no edition data in this environment; needs verification against staging/prod data

Screenshots

Mockup from the issue (pixel-verified: Borrow=blue, Buy=grey secondary in normal state):

Design mockup

mekarpeles added 27 commits June 4, 2026 14:06
- LocateButton: rewrite as secondary 'Check Worldcat' (has OCLC/ISBN)
  or 'Not Available'; removes off-site redirect
- LoanStatus: suppress Locate on non-book-page views (carousels, search
  results, editions table); pass worldcat_url through to ReadButton
- ReadButton: replace edition_key with worldcat_url; add book-open icon
  to Borrow/Read button; add WorldCat as dropdown item alongside Listen
- databarWork: remove desktop-vendor panel; add Buy OlPopover with
  affiliate links; Buy is primary (blue) only when no digital access
- BookPreview: rename 'Preview'/'Preview Only' -> 'Search Inside Preview'
  with search icon (icon_search-inside.svg)
- view.html: compute worldcat_url from OCLC/ISBN; remove mobile-vendor
  panel; add dismissible unavailability toast linking to #related-work-carousel
- borrow.py: remove dead action=locate -> WorldCat redirect
- read-panel.css: add book-open + cart icon classes; buy-popover styles;
  switch Preview ::before icon to icon_search-inside.svg

Closes #12826
Pre-existing regression from 3c3247c (Python 3.14 update). Comma-separated
except clauses are a SyntaxError in Python 3.
Completes fix for regression in 3c3247c: all bare comma-separated
except clauses are a SyntaxError in Python 3.
Site type annotation was evaluated at runtime in Python 3.12,
causing NameError on startup. from __future__ import annotations
defers all annotation evaluation, consistent with Python 3.14+ behavior.
TYPE_CHECKING-only imports used in runtime annotations cause NameError
in Python 3.12. Deferred annotation evaluation (PEP 563) fixes all of
them. Root cause: regression from Python 3.14 migration in #12643.
Bulk fix for annotation evaluation failures introduced by the Python
3.14 migration in #12643. All 300 openlibrary Python files now use
deferred annotation evaluation (PEP 563) to prevent NameError on
TYPE_CHECKING-only imports and forward references.
warnings.deprecated was added in Python 3.13; Docker image runs 3.12.
Adds try/except shim in the 4 files that import it.
Replaces runtime-evaluated TYPE_CHECKING annotations with quoted strings
in 3 files that are in the startup import path. Safer than blanket
from __future__ import annotations which breaks web.py handler registration.
When @deprecated wraps a class (not a function), the fallback shim was
returning a function wrapper, breaking inheritance of delegate.page
subclasses. Add isinstance(f, type) guard to pass classes through.
Templetor (web.py template engine) does not support multi-line $ expressions.
Collapse the _has_digital and _show_unavailable_toast bool checks to single
lines in databarWork.html and view.html.
Copilot AI review requested due to automatic review settings June 5, 2026 22:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR consolidates the edition (book) page left-sidebar CTAs into a single “Borrow/Read + Buy” card (moving WorldCat into the Borrow dropdown and adding a Buy <ol-popover>), adds an “unavailable” banner on edition pages, and includes a broad sweep of Python 3.14 compatibility fixes (future annotations + modern except (...) syntax + warnings.deprecated shims).

Changes:

  • Consolidates edition-page sidebar CTAs: WorldCat becomes a “Check WorldCat” option in the Borrow dropdown; affiliate purchase links move into a Buy <ol-popover>; removes legacy vendor panels.
  • Adds an edition-page dismissible banner when the book isn’t available on OL, linking to #related-work-carousel.
  • Applies Python 3.14 compatibility fixes across scripts/core/plugins/tests (future annotations, except tuple syntax, and deprecated shim fallback).

Reviewed changes

Copilot reviewed 76 out of 77 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
static/images/icons/icon_cart.svg Adds new cart icon asset for the Buy button.
static/css/components/read-panel.css Updates preview icon mask; adds styles for new Borrow/Buy icons and buy popover layout.
scripts/utils/scheduler.py Adds future annotations import for runtime annotation compatibility.
scripts/solr_updater/trending_updater.py Fixes Python 3 except (...) tuple syntax.
scripts/solr_updater/trending_updater_hourly.py Adds future annotations import.
scripts/providers/isbndb.py Fixes Python 3 except (...) tuple syntax.
scripts/providers/import_wikisource.py Adds future annotations import.
scripts/partner_batch_imports.py Fixes Python 3 except (...) tuple syntax.
scripts/monitoring/utils.py Adds future annotations import.
scripts/monitoring/solr_logs_monitor.py Adds future annotations import.
scripts/monitoring/monitor.py Fixes Python 3 except (...) tuple syntax.
scripts/affiliate_server.py Adds future annotations import (but currently disrupts shebang placement).
openlibrary/utils/sentry.py Adds future annotations import.
openlibrary/utils/schema.py Adds future annotations import.
openlibrary/utils/request_context.py Adds future annotations import; adjusts annotations to avoid runtime evaluation issues.
openlibrary/tests/solr/updater/test_work.py Adds future annotations import.
openlibrary/tests/solr/test_update.py Adds future annotations import.
openlibrary/tests/core/test_vendors.py Adds future annotations import.
openlibrary/templates/type/edition/view.html Computes worldcat_url, adds unavailable banner, updates databarWork invocation, removes mobile vendor panel.
openlibrary/solr/utils.py Adds future annotations import.
openlibrary/solr/updater/work.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/solr/updater/edition.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/solr/updater/abstract.py Adds future annotations import.
openlibrary/solr/update.py Adds future annotations import.
openlibrary/solr/data_provider.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/plugins/worksearch/subjects.py Adds future annotations import.
openlibrary/plugins/worksearch/schemes/subjects.py Adds future annotations import.
openlibrary/plugins/worksearch/schemes/lists.py Adds future annotations import.
openlibrary/plugins/worksearch/schemes/authors.py Adds future annotations import.
openlibrary/plugins/worksearch/schemes/init.py Adds future annotations import.
openlibrary/plugins/worksearch/code.py Adds future annotations import.
openlibrary/plugins/worksearch/autocomplete.py Adds future annotations import.
openlibrary/plugins/upstream/utils.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/plugins/upstream/tests/test_utils.py Adds future annotations import.
openlibrary/plugins/upstream/table_of_contents.py Adds future annotations import.
openlibrary/plugins/upstream/mybooks.py Adds future annotations import; adds warnings.deprecated fallback shim for older Pythons.
openlibrary/plugins/upstream/checkins.py Adds warnings.deprecated fallback shim for older Pythons.
openlibrary/plugins/upstream/borrow.py Removes dead action=locate → WorldCat redirect path.
openlibrary/plugins/upstream/addbook.py Adds future annotations import.
openlibrary/plugins/upstream/account.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/plugins/openlibrary/status.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/plugins/openlibrary/partials.py Adds future annotations import.
openlibrary/plugins/openlibrary/lists.py Adds future annotations import; adds warnings.deprecated fallback shim.
openlibrary/plugins/openlibrary/connection.py Adds future annotations import.
openlibrary/plugins/openlibrary/api.py Adds warnings.deprecated fallback shim; fixes Python 3 except (...) tuple syntax.
openlibrary/plugins/importapi/import_ui.py Adds future annotations import.
openlibrary/plugins/books/dynlinks.py Adds future annotations import.
openlibrary/plugins/admin/graphs.py Adds future annotations import.
openlibrary/plugins/admin/code.py Adds future annotations import.
openlibrary/macros/ReadButton.html Updates macro to accept worldcat_url, adds icon+label layout, and moves WorldCat into dropdown.
openlibrary/macros/LocateButton.html Replaces Locate button with “Check WorldCat” / “Not Available” secondary-state CTA.
openlibrary/macros/LoanStatus.html Passes worldcat_url through to Read/Locate button logic; suppresses Locate off book pages.
openlibrary/macros/databarWork.html Consolidates sidebar: removes vendor panel; adds Buy <ol-popover> with affiliate links; passes worldcat_url into LoanStatus.
openlibrary/macros/BookPreview.html Renames Preview CTA to “Search Inside Preview”.
openlibrary/i18n/validators.py Adds future annotations import.
openlibrary/fastapi/cdn.py Fixes Python 3 except (...) tuple syntax.
openlibrary/coverstore/utils.py Fixes Python 3 except (...) tuple syntax.
openlibrary/coverstore/schema.py Adds future annotations import.
openlibrary/coverstore/db.py Adds future annotations import.
openlibrary/coverstore/coverlib.py Adds future annotations import.
openlibrary/coverstore/code.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/core/wikidata.py Adds future annotations import.
openlibrary/core/waitinglist.py Adds future annotations import.
openlibrary/core/vendors.py Fixes Python 3 except (...) tuple syntax.
openlibrary/core/ratings.py Adds future annotations import.
openlibrary/core/models.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/core/lists/model.py Adds future annotations import.
openlibrary/core/imports.py Adds future annotations import.
openlibrary/core/ia.py Adjusts return annotation stringification to avoid runtime evaluation issues.
openlibrary/core/helpers.py Adds future annotations import; stringifies return annotation to avoid runtime evaluation issues.
openlibrary/core/env.py Adds future annotations import.
openlibrary/core/edits.py Fixes Python 3 except (...) tuple syntax.
openlibrary/core/db.py Fixes Python 3 except (...) tuple syntax.
openlibrary/core/cache.py Fixes Python 3 except (...) tuple syntax.
openlibrary/core/bookshelves.py Adds future annotations import.
openlibrary/core/batch_imports.py Adds future annotations import.
openlibrary/core/auth.py Adds future annotations import.
openlibrary/core/admin.py Fixes Python 3 except (...) tuple syntax.
openlibrary/catalog/utils/init.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.
openlibrary/catalog/marc/marc_xml.py Adds future annotations import.
openlibrary/catalog/marc/marc_binary.py Adds future annotations import.
openlibrary/catalog/marc/marc_base.py Adds future annotations import.
openlibrary/catalog/add_book/match.py Fixes Python 3 except (...) tuple syntax.
openlibrary/catalog/add_book/load_book.py Adds future annotations import.
openlibrary/catalog/add_book/init.py Adds future annotations import; stringifies forward-ref annotations.
openlibrary/book_providers.py Adds future annotations import.
openlibrary/app.py Adds future annotations import.
openlibrary/accounts/model.py Adds future annotations import.
openlibrary/accounts/init.py Adds future annotations import; fixes Python 3 except (...) tuple syntax.

Comment thread scripts/affiliate_server.py Outdated
Comment on lines 1 to 3
from __future__ import annotations

#!/usr/bin/env python
Comment on lines +290 to +298
/* Book-open icon for Borrow/Read buttons */
.btn-notice .btn-icon.book-open,
.read-options .btn-icon.book-open {
-webkit-mask: url(/static/images/icons/open-book.svg);
mask: url(/static/images/icons/open-book.svg);
-webkit-mask-size: cover;
mask-size: cover;
background-color: var(--white);
}
Comment on lines +8 to +11
data-ol-link-track="CTAClick|CheckWorldcat">
<span class="btn-icon map"></span>
<span class="btn-label">$_("Check Worldcat")</span>
</a>
Comment on lines +53 to +59
<a href="$worldcat_url"
target="_blank" rel="noopener noreferrer"
data-ol-link-track="CTAClick|CheckWorldcat"
class="cta-btn cta-btn--available cta-btn--w-icon">
<span class="btn-icon map"></span>
<span class="btn-label">$_("Check Worldcat")</span>
</a>
mekarpeles and others added 2 commits June 5, 2026 17:03
- Move shebang to line 1 in affiliate_server.py (future import was before shebang, breaking executability)
- Add standalone .btn-icon.map styles to read-panel.css (map icon was only styled inside .dropper-menu, so Check WorldCat button icon was invisible)
- Fix capitalization: "Worldcat" → "WorldCat" in LocateButton.html and ReadButton.html (proper product name, consistent with existing WorldcatLink.html)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Design: Consolidate book page left sidebar into a single CTA card

2 participants