Skip to content

Commit

Permalink
Hyphenate ISBN numbers and add copy button
Browse files Browse the repository at this point in the history
  • Loading branch information
ignorantFid authored and axiomizer committed Jul 25, 2023
1 parent 07aca2f commit bd26da3
Show file tree
Hide file tree
Showing 12 changed files with 8,044 additions and 12 deletions.
7,904 changes: 7,904 additions & 0 deletions bookwyrm/isbn/RangeMessage.xml

Large diffs are not rendered by default.

Empty file added bookwyrm/isbn/__init__.py
Empty file.
71 changes: 71 additions & 0 deletions bookwyrm/isbn/isbn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import os
import requests

from xml.etree import ElementTree
from bookwyrm import settings


class IsbnHyphenator:
__range_message_url = "https://www.isbn-international.org/export_rangemessage.xml"
__range_file_path = os.path.join(
settings.BASE_DIR, "bookwyrm", "isbn", "RangeMessage.xml"
)
__element_tree = None

def update_range_message(self):
response = requests.get(self.__range_message_url)
with open(self.__range_file_path, "w", encoding="utf-8") as file:
file.write(response.text)
self.__element_tree = None

def hyphenate(self, isbn_13):
if self.__element_tree is None:
self.__element_tree = ElementTree.parse(self.__range_file_path)
gs1_prefix = isbn_13[:3]
reg_group = self.__find_reg_group(isbn_13, gs1_prefix)
if reg_group is None:
return isbn_13 # failed to hyphenate
registrant = self.__find_registrant(isbn_13, gs1_prefix, reg_group)
if registrant is None:
return isbn_13 # failed to hyphenate
publication = isbn_13[len(gs1_prefix) + len(reg_group) + len(registrant) : -1]
check_digit = isbn_13[-1:]
return "-".join((gs1_prefix, reg_group, registrant, publication, check_digit))

def __find_reg_group(self, isbn_13, gs1_prefix):
for ean_ucc_el in self.__element_tree.find("EAN.UCCPrefixes").findall(
"EAN.UCC"
):
if ean_ucc_el.find("Prefix").text == gs1_prefix:
for rule_el in ean_ucc_el.find("Rules").findall("Rule"):
length = int(rule_el.find("Length").text)
if length == 0:
continue
range = [
int(x[:length]) for x in rule_el.find("Range").text.split("-")
]
reg_group = isbn_13[len(gs1_prefix) : len(gs1_prefix) + length]
if range[0] <= int(reg_group) <= range[1]:
return reg_group
return None
return None

def __find_registrant(self, isbn_13, gs1_prefix, reg_group):
from_ind = len(gs1_prefix) + len(reg_group)
for group_el in self.__element_tree.find("RegistrationGroups").findall("Group"):
if group_el.find("Prefix").text == "-".join((gs1_prefix, reg_group)):
for rule_el in group_el.find("Rules").findall("Rule"):
length = int(rule_el.find("Length").text)
if length == 0:
continue
range = [
int(x[:length]) for x in rule_el.find("Range").text.split("-")
]
registrant = isbn_13[from_ind : from_ind + length]
if range[0] <= int(registrant) <= range[1]:
return registrant
return None
return None


hyphenator_singleton = IsbnHyphenator()
28 changes: 28 additions & 0 deletions bookwyrm/static/css/bookwyrm/components/_copy.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,31 @@
.vertical-copy button {
width: 100%;
}

.copy-tooltip {
overflow: visible;
visibility: hidden;
width: 140px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
margin-left: -30px;
margin-top: -45px;
opacity: 0;
transition: opacity 0.3s;
}

.copy-tooltip::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -60px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
Binary file modified bookwyrm/static/css/fonts/icomoon.eot
Binary file not shown.
1 change: 1 addition & 0 deletions bookwyrm/static/css/fonts/icomoon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified bookwyrm/static/css/fonts/icomoon.ttf
Binary file not shown.
Binary file modified bookwyrm/static/css/fonts/icomoon.woff
Binary file not shown.
13 changes: 8 additions & 5 deletions bookwyrm/static/css/vendor/icons.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
@font-face {
font-family: 'icomoon';
src: url('../fonts/icomoon.eot?r7jc98');
src: url('../fonts/icomoon.eot?r7jc98#iefix') format('embedded-opentype'),
url('../fonts/icomoon.ttf?r7jc98') format('truetype'),
url('../fonts/icomoon.woff?r7jc98') format('woff'),
url('../fonts/icomoon.svg?r7jc98#icomoon') format('svg');
src: url('../fonts/icomoon.eot?nr4nq7');
src: url('../fonts/icomoon.eot?nr4nq7#iefix') format('embedded-opentype'),
url('../fonts/icomoon.ttf?nr4nq7') format('truetype'),
url('../fonts/icomoon.woff?nr4nq7') format('woff'),
url('../fonts/icomoon.svg?nr4nq7#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
Expand Down Expand Up @@ -122,6 +122,9 @@
.icon-graphic-banknote:before {
content: "\e920";
}
.icon-copy:before {
content: "\e92c";
}
.icon-search:before {
content: "\e986";
}
Expand Down
17 changes: 17 additions & 0 deletions bookwyrm/static/js/bookwyrm.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ let BookWyrm = new (class {
.querySelectorAll('input[type="file"]')
.forEach(bookwyrm.disableIfTooLarge.bind(bookwyrm));
document.querySelectorAll("[data-copytext]").forEach(bookwyrm.copyText.bind(bookwyrm));
document
.querySelectorAll("[data-copywithtooltip]")
.forEach(bookwyrm.copyWithTooltip.bind(bookwyrm));
document
.querySelectorAll(".modal.is-active")
.forEach(bookwyrm.handleActiveModal.bind(bookwyrm));
Expand Down Expand Up @@ -524,6 +527,20 @@ let BookWyrm = new (class {
textareaEl.parentNode.appendChild(copyButtonEl);
}

copyWithTooltip(copyButtonEl) {
const text = document.getElementById(copyButtonEl.dataset.contentId).innerHTML;
const tooltipEl = document.getElementById(copyButtonEl.dataset.tooltipId);
copyButtonEl.addEventListener("click", () => {
navigator.clipboard.writeText(text);
tooltipEl.style.visibility = "visible";
tooltipEl.style.opacity = 1;
setTimeout(function() {
tooltipEl.style.visibility = "hidden";
tooltipEl.style.opacity = 0;
}, 3000)
})
}

/**
* Handle the details dropdown component.
*
Expand Down
20 changes: 13 additions & 7 deletions bookwyrm/templates/book/book_identifiers.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,48 @@
{% if book.isbn_13 or book.oclc_number or book.asin or book.aasin or book.isfdb %}
<dl>
{% if book.isbn_13 %}
<div class="is-flex">
<div class="is-flex is-flex-wrap-wrap">
<dt class="mr-1">{% trans "ISBN:" %}</dt>
<dd itemprop="isbn">{{ book.isbn_13 }}</dd>
<dd itemprop="isbn" class="mr-1" id="isbn_content">{{ hyphenated_isbn13 }}</dd>
<div>
<button class="button is-small" data-copywithtooltip data-content-id="isbn_content" data-tooltip-id="isbn_tooltip">
<span class="icon icon-copy" title="{% trans "Copy ISBN" %}"></span>
</button>
<span class="copy-tooltip" id="isbn_tooltip">{% trans "Copied ISBN!" %}</span>
</div>
</div>
{% endif %}

{% if book.oclc_number %}
<div class="is-flex">
<div class="is-flex is-flex-wrap-wrap">
<dt class="mr-1">{% trans "OCLC Number:" %}</dt>
<dd>{{ book.oclc_number }}</dd>
</div>
{% endif %}

{% if book.asin %}
<div class="is-flex">
<div class="is-flex is-flex-wrap-wrap">
<dt class="mr-1">{% trans "ASIN:" %}</dt>
<dd>{{ book.asin }}</dd>
</div>
{% endif %}

{% if book.aasin %}
<div class="is-flex">
<div class="is-flex is-flex-wrap-wrap">
<dt class="mr-1">{% trans "Audible ASIN:" %}</dt>
<dd>{{ book.aasin }}</dd>
</div>
{% endif %}

{% if book.isfdb %}
<div class="is-flex">
<div class="is-flex is-flex-wrap-wrap">
<dt class="mr-1">{% trans "ISFDB ID:" %}</dt>
<dd>{{ book.isfdb }}</dd>
</div>
{% endif %}

{% if book.goodreads_key %}
<div class="is-flex">
<div class="is-flex is-flex-wrap-wrap">
<dt class="mr-1">{% trans "Goodreads:" %}</dt>
<dd>{{ book.goodreads_key }}</dd>
</div>
Expand Down
2 changes: 2 additions & 0 deletions bookwyrm/views/books/books.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from bookwyrm.activitypub import ActivitypubResponse
from bookwyrm.connectors import connector_manager, ConnectorException
from bookwyrm.connectors.abstract_connector import get_image
from bookwyrm.isbn.isbn import hyphenator_singleton as hyphenator
from bookwyrm.settings import PAGE_LENGTH
from bookwyrm.views.helpers import is_api_request, maybe_redirect_local_path

Expand Down Expand Up @@ -90,6 +91,7 @@ def get(self, request, book_id, **kwargs):
"rating": reviews.aggregate(Avg("rating"))["rating__avg"],
"lists": lists,
"update_error": kwargs.get("update_error", False),
"hyphenated_isbn13": hyphenator.hyphenate(book.isbn_13),
}

if request.user.is_authenticated:
Expand Down

0 comments on commit bd26da3

Please sign in to comment.