From: Radek Czajka <rczajka@rczajka.pl> Date: Thu, 28 Sep 2023 07:18:58 +0000 (+0200) Subject: Assigning isbn. X-Git-Url: https://git.mdrn.pl/redakcja.git/commitdiff_plain/91a20d3c82e0edcd883148b14df90b56a38ba2b2 Assigning isbn. --- diff --git a/src/documents/templates/documents/book_detail.html b/src/documents/templates/documents/book_detail.html index f534cd69..a286302f 100644 --- a/src/documents/templates/documents/book_detail.html +++ b/src/documents/templates/documents/book_detail.html @@ -2,6 +2,7 @@ {% load book_list i18n %} {% load bootstrap4 %} {% load depot %} +{% load isbn %} {% block titleextra %}{{ book.title }}{% endblock %} @@ -125,6 +126,8 @@ <a href="{% url 'documents_book_mobi' book.slug %}" rel="nofollow">{% trans "MOBI version" %}</a><br/> </p> + {% isbn_status book %} + {% if user.is_authenticated %} <!-- Angel photos: diff --git a/src/documents/templatetags/documents.py b/src/documents/templatetags/documents.py index b0a34bc9..b694e22b 100644 --- a/src/documents/templatetags/documents.py +++ b/src/documents/templatetags/documents.py @@ -37,6 +37,7 @@ def main_tabs(context): tabs.append(Tab('upload', _('Upload'), reverse("documents_upload"))) tabs.append(Tab('cover', _('Covers'), reverse("cover_image_list"))) + tabs.append(Tab('isbn', 'ISBN', reverse("isbn_list"))) return {"tabs": tabs, "active_tab": active} diff --git a/src/isbn/models.py b/src/isbn/models.py index 43d01bfc..d2d62909 100644 --- a/src/isbn/models.py +++ b/src/isbn/models.py @@ -1,3 +1,4 @@ +from datetime import date from django.apps import apps from django.db import models from lxml import etree @@ -114,6 +115,36 @@ class Isbn(models.Model): def get_code(self, dashes=True): return self.pool.get_code(self.suffix, dashes=dashes) + @classmethod + def get_for_book(cls, book, form): + isbn = cls.objects.filter(book=book, form=form).first() + if isbn is None: + return cls.assign(book, form) + return isbn + + @classmethod + def assign(cls, book, form): + pool = IsbnPool.objects.filter(purpose=IsbnPool.PURPOSE_WL).first() + suffix = pool.isbn_set.aggregate(s=models.Max('suffix'))['s'] + 1 + assert suffix <= pool.suffix_to + return pool.isbn_set.create( + book=book, form=form, suffix=suffix, datestamp=date.today() + ) + + @classmethod + def formats_from_document(cls, document): + # This is a document + meta = document.wldocument(librarian2=True).meta + is_parent = len(meta.parts) + formats = [] + for form, config in FORMS: + if config.book and (not is_parent or config.parent): + formats.append(( + form, + getattr(meta, f'isbn_{form}') + )) + return formats + @classmethod def import_from_documents(cls): Book = apps.get_model('documents', 'Book') diff --git a/src/isbn/product_forms.py b/src/isbn/product_forms.py index 206ca1d2..1d81c10d 100644 --- a/src/isbn/product_forms.py +++ b/src/isbn/product_forms.py @@ -1,10 +1,14 @@ +from collections import namedtuple + +FormConfig = namedtuple('FormConfig', ['book', 'parent', 'product_form', 'product_form_detail']) + FORMS = [ - ('html', ('EC', 'E105')), - ('txt', ('EB', 'E112')), - ('pdf', ('EB', 'E107')), - ('epub', ('ED', 'E101')), - ('mobi', ('ED', 'E127')), - ('mp3', ('AN', 'A103')), - ('paperback', ('BC', '')), + ('html', FormConfig(True, False, 'EC', 'E105')), + ('txt', FormConfig(True, False, 'EB', 'E112')), + ('pdf', FormConfig(True, True, 'EB', 'E107')), + ('epub', FormConfig(True, True, 'ED', 'E101')), + ('mobi', FormConfig(True, True, 'ED', 'E127')), + ('mp3', FormConfig(False, False, 'AN', 'A103')), + ('paperback', FormConfig(False, False, 'BC', '')), ] diff --git a/src/isbn/templates/isbn/isbn_status.html b/src/isbn/templates/isbn/isbn_status.html new file mode 100644 index 00000000..c46204f7 --- /dev/null +++ b/src/isbn/templates/isbn/isbn_status.html @@ -0,0 +1,19 @@ +<div class="row mb-4"> + <div class="col-4"> + ISBN + {% for form, value in formats %} + <span class="badge badge-{% if value %}primary{% else %}secondary{% endif %}" title="{{ value }}">{{ form }}</span> + {% endfor %} + </div> + <div class="col-4"> + {% if can_generate %} + <form method="post" action="{% url 'isbn_generate' book.pk %}"> + {% csrf_token %} + <button class="btn btn-primary btn-sm"> + uzupeÅnij + </button> + </form> + {% endif %} + {{ error }} + </div> +</div> diff --git a/src/isbn/templatetags/isbn.py b/src/isbn/templatetags/isbn.py new file mode 100644 index 00000000..263842e3 --- /dev/null +++ b/src/isbn/templatetags/isbn.py @@ -0,0 +1,36 @@ +from django.template import Library +from isbn.models import Isbn + + +register = Library() + + +@register.inclusion_tag('isbn/isbn_status.html', takes_context=True) +def isbn_status(context, book): + user = context['request'].user + formats = Isbn.formats_from_document(book) + + can_generate = False + error = '' + for f, v in formats: + if not v: + can_generate = True + + if can_generate: + if not user.has_perm('isbn.add_isbn'): + can_generate = False + + if can_generate: + try: + book.catalogue_book + except: + can_generate = False + error = 'Brak ksiÄ Å¼ki w katalogu.' + + return { + 'book': book, + 'formats': formats, + 'can_generate': can_generate, + 'error': error, + } + diff --git a/src/isbn/urls.py b/src/isbn/urls.py index a27781a7..afd00566 100644 --- a/src/isbn/urls.py +++ b/src/isbn/urls.py @@ -4,4 +4,5 @@ from . import views urlpatterns = [ path('', views.isbn_list, name='isbn_list'), + path('genarate/<int:document_id>/', views.generate, name='isbn_generate'), ] diff --git a/src/isbn/views.py b/src/isbn/views.py index 70c101ac..acf76c74 100644 --- a/src/isbn/views.py +++ b/src/isbn/views.py @@ -1,4 +1,8 @@ -from django.shortcuts import render +from django.contrib.auth.decorators import permission_required +from django.shortcuts import render, get_object_or_404, redirect +from librarian import DCNS, RDFNS +from lxml import etree +from documents.models import Book from .models import Isbn, IsbnPool @@ -7,3 +11,45 @@ def isbn_list(request): 'pools': IsbnPool.objects.all(), 'list': Isbn.objects.all(), }) + + +MIME = { + 'html': 'text/html', + 'pdf': 'application/pdf', + 'txt': 'text/plain', + 'epub': 'application/epub+zip', + 'mobi': 'application/x-mobipocket-ebook', +} + + +@permission_required('isbn.add_isbn') +def generate(request, document_id): + document = get_object_or_404(Book, id=document_id) + book = document.catalogue_book + chunk = document[0] + head = chunk.head + orig_xml = head.materialize() + tree = etree.fromstring(orig_xml) + rdfdesc = tree.find('.//' + RDFNS('Description')) + + for form, value in Isbn.formats_from_document(document): + if value: continue + isbn = Isbn.get_for_book(book, form) + + etree.SubElement(rdfdesc, DCNS('relation.hasFormat'), id="mobi").text = f"https://wolnelektury.pl/media/book/{form}mobi/{book.slug}.{form}" + etree.SubElement( + rdfdesc, 'meta', refines=f'#{form}', id=f'{form}-id', property='dcterms:identifier' + ).text = 'ISBN-' + isbn.get_code(True) + etree.SubElement(rdfdesc, 'meta', refines=f'#{form}-id', property='identifier-type').text = 'ISBN' + etree.SubElement(rdfdesc, 'meta', refines=f'#{form}', property='dcterms:format').text = MIME[form] + + xml = etree.tostring(tree, encoding='unicode') + chunk.commit( + text=xml, + author=request.user, + parent=head, + description='Auto ISBN', + publishable=head.publishable + ) + + return redirect(document.get_absolute_url())