From: Radek Czajka Date: Wed, 3 Apr 2024 08:47:05 +0000 (+0200) Subject: project sell info and initial synchro support X-Git-Url: https://git.mdrn.pl/redakcja.git/commitdiff_plain/0f2ac86f03177aebee66a3890120d9926272cf27?ds=sidebyside;hp=2dd9e6498b5e0bd5c0bd882db02be9768c34c019 project sell info and initial synchro support --- diff --git a/src/cover/templates/cover/image_detail.html b/src/cover/templates/cover/image_detail.html index c357ff0e..6a67eecc 100644 --- a/src/cover/templates/cover/image_detail.html +++ b/src/cover/templates/cover/image_detail.html @@ -74,7 +74,11 @@ {% for book in object.book_set.all %}
  • - {{ book }} + {% if book.cover %} + {{ book }} + {% else %} + {{ book }} + {% endif %}
  • {% endfor %} diff --git a/src/documents/migrations/0016_project_can_sell_project_private_notes.py b/src/documents/migrations/0016_project_can_sell_project_private_notes.py new file mode 100644 index 00000000..edb298c1 --- /dev/null +++ b/src/documents/migrations/0016_project_can_sell_project_private_notes.py @@ -0,0 +1,23 @@ +# Generated by Django 4.1.9 on 2024-04-03 10:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("documents", "0015_project_logo_alt"), + ] + + operations = [ + migrations.AddField( + model_name="project", + name="can_sell", + field=models.BooleanField(default=True, verbose_name="Do sprzedaży"), + ), + migrations.AddField( + model_name="project", + name="private_notes", + field=models.TextField(blank=True, verbose_name="Prywatne notatki"), + ), + ] diff --git a/src/documents/models/project.py b/src/documents/models/project.py index 7e9cf306..9efee5a6 100644 --- a/src/documents/models/project.py +++ b/src/documents/models/project.py @@ -13,6 +13,8 @@ class Project(models.Model): logo = models.FileField(upload_to='projects', blank=True) logo_mono = models.FileField(upload_to='logo_mono', help_text='white on transparent', blank=True) logo_alt = models.CharField(max_length=255, blank=True) + private_notes = models.TextField(blank=True, verbose_name='Prywatne notatki') + can_sell = models.BooleanField(default=True, verbose_name='Do sprzedaży') class Meta: app_label = 'documents' diff --git a/src/documents/templates/documents/book_detail.html b/src/documents/templates/documents/book_detail.html index 2d587349..b9dd6abe 100644 --- a/src/documents/templates/documents/book_detail.html +++ b/src/documents/templates/documents/book_detail.html @@ -70,7 +70,28 @@
    -

    {% trans "Publication" %}

    +

    + {% trans "Publication" %} + | + {% if book.project %} + {% if book.project.can_sell %} + 💶 + {% else %} + 🙅 + {% endif %} + {% else %} + ❓ + {% endif %} + {% if has_audio %} + | 🎧 + {% if can_sell_audio %} + 💶 + {% else %} + 🙅 + {% endif %} + {% endif %} +

    +
    @@ -127,6 +148,8 @@ {% trans "MOBI version" %}

    +

    Sprawdź synchronizację

    + {% isbn_status book %} {% if user.is_authenticated %} diff --git a/src/documents/templates/documents/synchro.html b/src/documents/templates/documents/synchro.html new file mode 100644 index 00000000..bc44673e --- /dev/null +++ b/src/documents/templates/documents/synchro.html @@ -0,0 +1,49 @@ +{% extends "documents/base.html" %} + + +{% block content %} + +
    +
    +
    +
    + {% if not length_ok %} +
    + Liczba znalezionych części dokumentu nie zgadza się z liczbą części audiobooka. + Konieczna jest korekta za pomocą atrybutów forcesplit i nosplit. +
    + {% else %} +
    + {% csrf_token %} + +
    + {% endif %} + +
    +
    + + + + + + + + + {% for h, m in table %} + + + + + {% endfor %} +
    Nagłówek cięciaAudiobook
    + {% if h %} + + {{ h.0 }} (linia {{ h.2 }}) + + {% else %} + — + {% endif %} + {{ m|default_if_none:'—' }}
    +{% endblock %} diff --git a/src/documents/urls.py b/src/documents/urls.py index d9114cc1..e7b68c27 100644 --- a/src/documents/urls.py +++ b/src/documents/urls.py @@ -45,6 +45,7 @@ urlpatterns = [ path('book//mobi', views.book_mobi, name="documents_book_mobi"), path('book//pdf', views.book_pdf, name="documents_book_pdf"), path('book//pdf-mobile', views.book_pdf, kwargs={'mobile': True}, name="documents_book_pdf_mobile"), + path('book//synchro', views.synchro, name="documents_book_synchro"), path('chunk_add///', views.chunk_add, name="documents_chunk_add"), diff --git a/src/documents/views.py b/src/documents/views.py index 905e885b..8f403034 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -2,7 +2,9 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from collections import defaultdict +from copy import deepcopy from datetime import datetime, date, timedelta +from itertools import zip_longest import logging import os from urllib.parse import quote_plus, unquote, urlsplit, urlunsplit @@ -22,8 +24,11 @@ from django.utils.encoding import iri_to_uri from django.utils.translation import gettext_lazy as _ from django.views.decorators.http import require_POST from django_cas_ng.decorators import user_passes_test +import requests from librarian import epubcheck +from librarian.html import raw_printable_text + from apiclient import api_call, NotAuthorizedError from . import forms from . import helpers @@ -404,6 +409,14 @@ def book(request, slug): except: pass + if book.catalogue_book_id: + audio_items = requests.get(f'https://audio.wolnelektury.pl/archive/book/{book.catalogue_book_id}.json').json()['items'] + has_audio = bool(audio_items) + can_sell_audio = has_audio and all(x['project']['can_sell'] for x in audio_items) + else: + has_audio = None + can_sell_audio = None + return render(request, "documents/book_detail.html", { "book": book, "doc": doc, @@ -413,6 +426,8 @@ def book(request, slug): "form": form, "publish_options_form": publish_options_form, "editable": editable, + "has_audio": has_audio, + "can_sell_audio": can_sell_audio, }) @@ -747,3 +762,81 @@ def mark_final(request): def mark_final_completed(request): return render(request, 'documents/mark_final_completed.html') + + +def synchro(request, slug): + book = get_object_or_404(Book, slug=slug) + if not book.accessible(request): + return HttpResponseForbidden("Not authorized.") + + document = book.wldocument(librarian2=True) + slug = document.meta.url.slug + print(f'https://audio.wolnelektury.pl/archive/book/{slug}.json') + error = None + try: + items = requests.get(f'https://audio.wolnelektury.pl/archive/book/{slug}.json').json()['items'] + except: + error = 'Błąd połączenia z repozytorium audio.' + items = [] + else: + mp3 = [ + item['part'] for item in items + ] + + split_on = ( + 'naglowek_rozdzial', + 'naglowek_scena', + ) + + if split_on: + documents = [] + headers = [('Początek', 0, 0)] + present = True + n = 0 + while present: + present = False + n += 1 + newdoc = deepcopy(document) + newdoc.tree.getroot().document = newdoc + + master = newdoc.tree.getroot()[-1] + i = 0 + for item in list(master): + #chunkno, sourceline = 0, self.sourceline + #if builder.splits: + # chunkno, sourceline = len(builder.splits), sourceline - builder.splits[-1] + + if 'forcesplit' in item.attrib or (item.tag in split_on and 'nosplit' not in item.attrib): + # TODO: clear + i += 1 + if n > 1 and i == n: + headers.append(( + raw_printable_text(item), + 0, + item.sourceline, + )) + if i != n and not (n == 1 and not i): + master.remove(item) + else: + present = True + if present: + documents.append(newdoc) + else: + documents = [document] + headers = [( + document.meta.title, 0 ,0 + )] + + length_ok = len(headers) == len(mp3) + table = zip_longest(headers, mp3) + + + return render(request, 'documents/synchro.html', { + 'book': book, + 'documents': documents, + 'headers': headers, + 'mp3': mp3, + 'length_ok': length_ok, + 'table': table, + 'error': error, + })