diff --git a/bundlesize.config.json b/bundlesize.config.json index d4e46bab4bd..afa5cda2da6 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -58,8 +58,7 @@ }, { "path": "static/build/css/page-admin.css", - "maxSize": "27KB" - + "maxSize": "28KB" }, { "path": "static/build/css/page-book.css", diff --git a/docker/Dockerfile.olbase b/docker/Dockerfile.olbase index e20dfd45490..1bdb76cf21f 100644 --- a/docker/Dockerfile.olbase +++ b/docker/Dockerfile.olbase @@ -85,4 +85,5 @@ RUN npm ci --no-audit COPY --chown=openlibrary:openlibrary . /openlibrary # run make to initialize git submodules, build css and js files RUN ln -s vendor/infogami/infogami infogami \ + && touch node_modules \ && make diff --git a/openlibrary/i18n/messages.pot b/openlibrary/i18n/messages.pot index a5c7150e043..28697e624d8 100644 --- a/openlibrary/i18n/messages.pot +++ b/openlibrary/i18n/messages.pot @@ -4344,7 +4344,7 @@ msgstr "" msgid "Provider Name" msgstr "" -#: books/edit/edition.html +#: books/edit/edition.html databarWork.html msgid "Buy" msgstr "" @@ -4765,7 +4765,7 @@ msgid "" " page for every book ever published." msgstr "" -#: AffiliateLinks.html.jinja home/about.html search/work_search_facets.html +#: home/about.html search/work_search_facets.html msgid "More" msgstr "" @@ -7140,10 +7140,6 @@ msgstr "" msgid "ISBNs" msgstr "" -#: databarWork.html type/edition/view.html type/work/view.html -msgid "Buy this book" -msgstr "" - #: type/edition/view.html type/work/view.html msgid "Book Details" msgstr "" @@ -8385,6 +8381,10 @@ msgstr "" msgid "View Volume %(num)d" msgstr "" +#: databarWork.html +msgid "Buy this book" +msgstr "" + #: openlibrary/core/bookshelves.py msgid "[Record deleted]" msgstr "" diff --git a/openlibrary/macros/AffiliateLinks.html.jinja b/openlibrary/macros/AffiliateLinks.html.jinja index 164f619505d..5e722130bf2 100644 --- a/openlibrary/macros/AffiliateLinks.html.jinja +++ b/openlibrary/macros/AffiliateLinks.html.jinja @@ -1,31 +1,24 @@ {% macro affiliate_link(store) %} -
  • - + {{ store.name }} - {% if store.price %} -
    - {{ store.price }}{{ store.price_note }} - {% endif %} -
  • + rel="noopener noreferrer"> + {{ store.name }} + {% if store.price %} + {{ store.price }}{{ store.price_note }} + {% endif %} + + {% endmacro %} - - - + {% for store in more_stores %}{{ affiliate_link(store) | safe }}{% endfor %} + + {{ _("When you buy books using these links the Internet Archive may earn a small commission.") | safe }} - + diff --git a/openlibrary/macros/AffiliateLinksLoadingIndicator.html b/openlibrary/macros/AffiliateLinksLoadingIndicator.html index 6ef6ed565ff..9c00d56232e 100644 --- a/openlibrary/macros/AffiliateLinksLoadingIndicator.html +++ b/openlibrary/macros/AffiliateLinksLoadingIndicator.html @@ -3,6 +3,6 @@ isbn_str = isbn or '' asin_str = asin or '' prices_str = 'true' if prices else 'false' - + diff --git a/openlibrary/macros/LoanStatus.html b/openlibrary/macros/LoanStatus.html index 253422ec1ab..b53ab07b8ce 100644 --- a/openlibrary/macros/LoanStatus.html +++ b/openlibrary/macros/LoanStatus.html @@ -1,4 +1,4 @@ -$def with (doc, work_key=None, listen=True, allow_expensive_availability_check=False, secondary_action=False, check_loan_status=False, user_lists=None, post='', is_book_page=False, analytics_override=None, lending_state=None) +$def with (doc, work_key=None, listen=True, allow_expensive_availability_check=False, secondary_action=False, check_loan_status=False, user_lists=None, is_book_page=False, analytics_override=None, lending_state=None) $# Takes following parameters: $# * doc - Can be a Work, Edition, or solr dict. $# * listen - whether to display listen button @@ -167,8 +167,6 @@ $else: $:macros.NotInLibrary(None, analytics_attr) -$:post - $if query_param('debug'): $ loanstatus_end_time = time() - loanstatus_start_time

    get_waiting_loan_for(ocaid) took $("%.2f" % waiting_loan_total_time) seconds

    $# detect-missing-i18n-skip-line diff --git a/openlibrary/macros/databarWork.html b/openlibrary/macros/databarWork.html index dbf7166bf55..1847ef44ca1 100644 --- a/openlibrary/macros/databarWork.html +++ b/openlibrary/macros/databarWork.html @@ -2,6 +2,11 @@ $ viewbook = "//%s/stream/XXX?ref=ol" % bookreader_host() +$# Buy button is primary (blue) only when no digital access and a WorldCat URL exists +$ availability = (page.availability or {}) if hasattr(page, 'availability') else {} +$ _has_digital = bool(page.get('ocaid') or availability.get('is_readable') or availability.get('status') == 'open' or availability.get('is_lendable') or availability.get('is_previewable')) +$ buy_is_primary = editions_page and not _has_digital and bool(worldcat_url) +
    $if page.volumes: @@ -28,17 +33,30 @@

    $ work = (page.works and page.works[0]) or page $ edition = page.works and page - $ render_times['databarWork: List widget'] = time() - $ lists_widget = render_template('lists/widget', edition or work, include_rating=True, async_load=True) - $ render_times['databarWork: List widget'] = time() - render_times['databarWork: List widget'] $# For the Works & Editions page, only use ground_truth_availability API for selected Edition $# if edition availability status is error $ render_times['databarWork: LoanStatus'] = time() $ expensive_check = page.get('availability', {}).get('status') in ['error'] - $:macros.LoanStatus(page, allow_expensive_availability_check=expensive_check, secondary_action=editions_page, check_loan_status=editions_page, post=lists_widget, lending_state=lending_state) + $:macros.LoanStatus(page, allow_expensive_availability_check=expensive_check, secondary_action=editions_page, check_loan_status=editions_page, lending_state=lending_state) $ render_times['databarWork: LoanStatus'] = time() - render_times['databarWork: LoanStatus'] + $if editions_page: + + +
    + $:affiliate_links +
    +
    + + $ render_times['databarWork: List widget'] = time() + $:render_template('lists/widget', edition or work, include_rating=True, async_load=True) + $ render_times['databarWork: List widget'] = time() - render_times['databarWork: List widget'] +
    $ share_url = request.home + (edition or work).key @@ -64,16 +82,5 @@

    $ render_times['databarWork: Book provider'] = time() - render_times['databarWork: Book provider']

    - -
    -
    - $:worldcat_links - -
    -

    $_('Buy this book')

    - $:affiliate_links -
    -
    -
    diff --git a/openlibrary/templates/type/edition/view.html b/openlibrary/templates/type/edition/view.html index e4f3580b374..91223b313c9 100644 --- a/openlibrary/templates/type/edition/view.html +++ b/openlibrary/templates/type/edition/view.html @@ -306,19 +306,6 @@ -
    -
    -
    - $:worldcat_link - -
    -

    $_('Buy this book')

    - $:affiliate_links -
    -
    -
    -
    - $ seen = set() $if previews and any([len(e.languages) for e in previews]):

    diff --git a/static/css/components/read-panel.css b/static/css/components/read-panel.css index 80d9966b711..3240609a2d9 100644 --- a/static/css/components/read-panel.css +++ b/static/css/components/read-panel.css @@ -130,20 +130,6 @@ ul.ebook-download-options li { margin: 5px 0; } -.buy-options-table { - line-height: 2em; -} - -.buy-options-table .more { - margin-left: 0; - cursor: pointer; -} - -.buy-options-table + small { - display: block; - margin-top: 10px; -} - .cta-section-title.world-cat-link { margin-top: 0; } @@ -286,3 +272,111 @@ ul.ebook-download-options li { /* stylelint-enable selector-max-specificity */ /* stylelint-enable max-nesting-depth */ } + +/* Buy popover: full-width trigger button */ +.buy-popover { + display: block; + width: 100%; + margin-top: var(--spacing-stack-xs); +} + +/* Buy options popover content */ +.buy-options { + box-sizing: border-box; + width: 100%; + background-color: var(--white); + border-radius: var(--border-radius-overlay); +} + +@media only screen and (min-width: 768px) { + .buy-options { + width: 240px; + } +} + +.buy-options .buy-option { + transition: background-color 0.2s; +} + +.buy-options .buy-option:hover { + background-color: var(--lightest-grey); +} + +.buy-options .buy-option__link { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--spacing-inset-sm) var(--spacing-inset-md); + color: var(--dark-grey); + text-decoration: none; + font-size: var(--font-size-body-medium); +} + +.buy-options .buy-option__price { + font-size: var(--font-size-label-medium); + color: var(--accessible-grey); +} + +/* Disclaimer with top horizontal border */ +.buy-options .buy-options__disclaimer { + display: block; + padding: var(--spacing-inset-sm) var(--spacing-inset-md); + border-top: 1px solid var(--lighter-grey); + color: var(--accessible-grey); + font-size: var(--font-size-label-medium); + line-height: 1.4; +} + +.buy-options .buy-options__disclaimer a { + color: var(--link-blue); + text-decoration: underline; +} + +/* Buy button custom styling (single button with left icon and right arrow) */ +.cta-btn--buy { + position: relative; + background-color: var(--grey-464646); + color: var(--white); + margin-top: 0; + height: 37px; + padding: 0 var(--spacing-inset-sm); + display: flex; + align-items: center; + justify-content: center; +} + +.cta-btn--buy:hover { + background-color: var(--dark-grey); +} + +.cta-btn--buy .btn-icon.cart { + position: absolute; + left: 12px; +} + +.cta-btn--buy .btn-label { + padding: 0; +} + +.cta-btn--buy .arrow-down { + position: absolute; + right: 0; + top: 0; + width: 32px; + height: 100%; + border-left: 1px solid var(--grey); + display: flex; + align-items: center; + justify-content: center; +} + +.cta-btn--buy .arrow-down::after { + content: ""; + display: block; + width: 23px; + height: 23px; + background: url(/static/images/icons/icon_dropit.png) no-repeat center; + background-position: 0; + background-size: 45px; + filter: brightness(0) invert(1); +} diff --git a/static/css/components/work.css b/static/css/components/work.css index 3a2a7d1a285..27d77d17584 100644 --- a/static/css/components/work.css +++ b/static/css/components/work.css @@ -202,6 +202,9 @@ div.editionTools p { width: var(--sidebar-width); margin-right: 1.5em; margin-bottom: 0; + position: sticky; + top: 20px; + align-self: flex-start; } div.editionAbout { flex: 1;