python-docx==0.8.10
Wikidata==0.6.1
-librarian==2.2
+librarian==2.3.1
## Django
Django==3.1.13
--- /dev/null
+from django.contrib import admin
+from . import models
+
+
+@admin.register(models.Package)
+class PackageAdmin(admin.ModelAdmin):
+ filter_horizontal = ['books']
+ pass
+
+# Register your models here.
--- /dev/null
+from django.apps import AppConfig
+
+
+class DepotConfig(AppConfig):
+ name = 'depot'
--- /dev/null
+# Generated by Django 3.1.13 on 2021-12-17 15:36
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('documents', '0006_auto_20210706_0130'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Package',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('placed_at', models.DateTimeField(blank=True, null=True)),
+ ('finished_at', models.DateTimeField(blank=True, null=True)),
+ ('definition_json', models.TextField(blank=True)),
+ ('status_json', models.TextField(blank=True)),
+ ('logo', models.FileField(blank=True, upload_to='depot/logo')),
+ ('file', models.FileField(blank=True, upload_to='depot/package/')),
+ ('books', models.ManyToManyField(to='documents.Book')),
+ ],
+ ),
+ ]
--- /dev/null
+import json
+import os
+import tempfile
+import zipfile
+from datetime import datetime
+from django.db import models
+from librarian.cover import make_cover
+from librarian.builders import EpubBuilder, MobiBuilder
+
+
+class Package(models.Model):
+ created_at = models.DateTimeField(auto_now_add=True)
+ placed_at = models.DateTimeField(null=True, blank=True)
+ finished_at = models.DateTimeField(null=True, blank=True)
+ definition_json = models.TextField(blank=True)
+ books = models.ManyToManyField('documents.Book')
+ status_json = models.TextField(blank=True)
+ logo = models.FileField(blank=True, upload_to='depot/logo')
+ file = models.FileField(blank=True, upload_to='depot/package/')
+
+ def save(self, *args, **kwargs):
+ try:
+ self.set_status(self.get_status())
+ except:
+ pass
+
+ try:
+ self.set_definition(self.get_definition())
+ except:
+ pass
+
+ super().save(*args, **kwargs)
+
+ def get_status(self):
+ return json.loads(self.status_json)
+
+ def set_status(self, status):
+ self.status_json = json.dumps(status, indent=4)
+
+ def get_definition(self):
+ return json.loads(self.definition_json)
+
+ def set_definition(self, definition):
+ self.definition_json = json.dumps(definition, indent=4)
+
+ def build(self):
+ f = tempfile.NamedTemporaryFile(prefix='depot-', suffix='.zip', mode='wb', delete=False)
+ with zipfile.ZipFile(f, 'w') as z:
+ for book in self.books.all():
+ self.build_for(book, z)
+ f.close()
+ with open(f.name, 'rb') as ff:
+ self.file.save('package-{}.zip'.format(datetime.now().isoformat(timespec='seconds')), ff)
+ os.unlink(f.name)
+
+ def build_for(self, book, z):
+ wldoc2 = book.wldocument(librarian2=True)
+ slug = wldoc2.meta.url.slug
+ for item in self.get_definition():
+ wldoc = book.wldocument()
+ wldoc2 = book.wldocument(librarian2=True)
+ base_url = 'file://' + book.gallery_path() + '/'
+
+ ext = item['type']
+
+ if item['type'] == 'cover':
+ kwargs = {}
+ if self.logo:
+ kwargs['cover_logo'] = self.logo.path
+ for k in 'format', 'width', 'height', 'cover_class':
+ if k in item:
+ kwargs[k] = item[k]
+ cover = make_cover(wldoc.book_info, **kwargs)
+ output = cover.output_file()
+ ext = cover.ext()
+
+ elif item['type'] == 'pdf':
+ cover_kwargs = {}
+ if 'cover_class' in item:
+ cover_kwargs['cover_class'] = item['cover_class']
+ if self.logo:
+ cover_kwargs['cover_logo'] = self.logo.path
+ cover = lambda *args, **kwargs: make_cover(*args, **kwargs, **cover_kwargs)
+ output = wldoc.as_pdf(cover=cover, base_url=base_url)
+
+ elif item['type'] == 'epub':
+ cover_kwargs = {}
+ if 'cover_class' in item:
+ cover_kwargs['cover_class'] = item['cover_class']
+ if self.logo:
+ cover_kwargs['cover_logo'] = self.logo.path
+ cover = lambda *args, **kwargs: make_cover(*args, **kwargs, **cover_kwargs)
+
+ output = EpubBuilder(
+ cover=cover,
+ base_url=base_url,
+# fundraising=[]
+ ).build(wldoc2)
+
+ elif item['type'] == 'mobi':
+ output = MobiBuilder(
+ cover=cover,
+ base_url=base_url,
+ ).build(wldoc2)
+
+ fname = f'{slug}/{slug}.{ext}'
+
+ z.writestr(
+ fname,
+ output.get_bytes()
+ )
--- /dev/null
+from django.test import TestCase
+
+# Create your tests here.
--- /dev/null
+from django.shortcuts import render
+
+# Create your views here.
msgstr ""
"Project-Id-Version: Platforma Redakcyjna\n"
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2020-04-20 16:54+0200\n"
+"PO-Revision-Date: 2021-12-17 11:37+0100\n"
"Last-Translator: Radek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>\n"
"Language-Team: Fundacja Nowoczesna Polska <fundacja@nowoczesnapolska.org."
"pl>\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
-"X-Generator: Poedit 2.2.4\n"
+"X-Generator: Poedit 3.0\n"
#: documents/forms.py:41
msgid "Text file must be UTF-8 encoded."
msgid "scan gallery name"
msgstr "nazwa galerii skanów"
-#: documents/models/book.py:34
+#: documents/models/book.py:33
msgid "parent"
msgstr "rodzic"
-#: documents/models/book.py:35
+#: documents/models/book.py:34
msgid "parent number"
msgstr "numeracja rodzica"
-#: documents/models/book.py:53 documents/models/chunk.py:19
+#: documents/models/book.py:60 documents/models/chunk.py:19
#: documents/models/publish_log.py:15
+#: documents/templates/documents/book_detail.html:145
msgid "book"
msgstr "książka"
-#: documents/models/book.py:54 documents/views.py:619
+#: documents/models/book.py:61 documents/views.py:627
msgid "books"
msgstr "książki"
-#: documents/models/book.py:263
+#: documents/models/book.py:271
msgid "No chunks in the book."
msgstr "Książka nie ma części."
-#: documents/models/book.py:267
+#: documents/models/book.py:275
msgid "Not all chunks have publishable revisions."
msgstr "Niektóre części nie są gotowe do publikacji."
-#: documents/models/book.py:274 documents/models/image.py:83
+#: documents/models/book.py:282 documents/models/image.py:83
msgid "Invalid XML"
msgstr "Nieprawidłowy XML"
-#: documents/models/book.py:276 documents/models/image.py:85
+#: documents/models/book.py:284 documents/models/image.py:85
msgid "No Dublin Core found."
msgstr "Brak sekcji Dublin Core."
-#: documents/models/book.py:278 documents/models/image.py:87
+#: documents/models/book.py:286 documents/models/image.py:87
msgid "Invalid Dublin Core"
msgstr "Nieprawidłowy Dublin Core"
-#: documents/models/book.py:281 documents/models/image.py:91
+#: documents/models/book.py:289 documents/models/image.py:91
msgid "rdf:about is not"
msgstr "rdf:about jest różny od"
msgid "This book can't be published yet, because:"
msgstr "Ta książka nie może jeszcze zostać opublikowana. Powód:"
+#: documents/templates/documents/book_detail.html:138
+msgid "Statistics"
+msgstr "Statystyki"
+
+#: documents/templates/documents/book_detail.html:147
+msgid "characters"
+msgstr "znaki"
+
+#: documents/templates/documents/book_detail.html:148
+msgid "words"
+msgstr "słowa"
+
+#: documents/templates/documents/book_detail.html:149
+msgid "characters (with footnotes)"
+msgstr "znaki (z przypisami)"
+
+#: documents/templates/documents/book_detail.html:150
+msgid "words (with footnotes)"
+msgstr "słowa (z przypisami)"
+
#: documents/templates/documents/book_edit.html:5
msgid "Edit book"
msgstr "Edytuj książkę"
msgid "File should be UTF-8 encoded."
msgstr "Plik powinien mieć kodowanie UTF-8."
-#: documents/views.py:621
+#: documents/views.py:629
msgid "scan gallery"
msgstr "galeria skanów"
from documents.signals import post_publish
from documents.xml_tools import compile_text, split_xml
from cover.models import Image
+from io import BytesIO
import os
import shutil
import re
return compile_text(change.materialize() for change in changes)
def wldocument(self, publishable=True, changes=None,
- parse_dublincore=True, strict=False):
+ parse_dublincore=True, strict=False, librarian2=False):
from documents.ebook_utils import RedakcjaDocProvider
from librarian.parser import WLDocument
-
+ from librarian.document import WLDocument as WLDocument2
+
+ provider = RedakcjaDocProvider(publishable=publishable),
+ xml = self.materialize(publishable=publishable, changes=changes).encode('utf-8')
+
+ if librarian2:
+ return WLDocument2(
+ BytesIO(xml),
+ provider=provider)
return WLDocument.from_bytes(
- self.materialize(publishable=publishable, changes=changes).encode('utf-8'),
- provider=RedakcjaDocProvider(publishable=publishable),
+ xml,
+ provider=provider,
parse_dublincore=parse_dublincore,
strict=strict)
</div>
</div>
+</div>
+</div>
+
+{% if doc %}
+ <div class="card mt-4">
+ <div class="card-header">
+ <h2>{% trans "Statistics" %}</h2>
+ </div>
+ <div class="card-body">
+ <table class="table">
+ <thead>
+ <tr>
+ <th>
+ {% trans "book" %}
+ </th>
+ <th>{% trans "characters" %}</th>
+ <th>{% trans "words" %}</th>
+ <th>{% trans "characters (with footnotes)" %}</th>
+ <th>{% trans "words (with footnotes)" %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% with stats=book.wldocument.get_statistics %}
+ {% include 'documents/book_stats.html' with book=book stats=stats depth=0 %}
+ {% endwith %}
+ </tbody>
+ </table>
+ </div>
+ </div>
+{% endif %}
{% endblock content %}
# TODO: move to celery
doc = book.wldocument()
# TODO: error handling
- epub = doc.as_epub(base_url=request.build_absolute_uri(book.gallery_path())).get_bytes()
+
+ #### Problemas: images in children.
+ epub = doc.as_epub(base_url='file://' + book.gallery_path() + '/').get_bytes()
response = HttpResponse(content_type='application/epub+zip')
response['Content-Disposition'] = 'attachment; filename=%s' % book.slug + '.epub'
response.write(epub)
# TODO: move to celery
doc = book.wldocument()
# TODO: error handling
- mobi = doc.as_mobi(base_url=request.build_absolute_uri(book.gallery_path())).get_bytes()
+ mobi = doc.as_mobi(base_url='file://' + book.gallery_path() + '/').get_bytes()
response = HttpResponse(content_type='application/x-mobipocket-ebook')
response['Content-Disposition'] = 'attachment; filename=%s' % book.slug + '.mobi'
response.write(mobi)
publish_error = book.publishable_error()
publishable = publish_error is None
+ try:
+ doc = book.wldocument()
+ except:
+ doc = None
+
return render(request, "documents/book_detail.html", {
"book": book,
+ "doc": doc,
"publishable": publishable,
"publishable_error": publish_error,
"form": form,
'redakcja.api',
'catalogue',
+ 'depot',
'documents',
'cover',
'dvcs',