From 50c9721c6d15d8b60fb0525f72b6b06c95e0677d Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 28 Jan 2025 13:53:20 +0100 Subject: [PATCH 01/11] fix for postgres --- src/documents/models/chunk.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/documents/models/chunk.py b/src/documents/models/chunk.py index 4d8f6d23..797fc174 100644 --- a/src/documents/models/chunk.py +++ b/src/documents/models/chunk.py @@ -75,8 +75,10 @@ class Chunk(dvcs_models.Document): def split(self, slug, title='', **kwargs): """ Create an empty chunk after this one """ - self.book.chunk_set.filter(number__gt=self.number).update( - number=models.F('number')+1) + # Single update makes unique constr choke on postgres. + for chunk in self.book.chunk_set.filter(number__gt=self.number).order_by('-number'): + chunk.number += 1 + chunk.save() new_chunk = None while not new_chunk: new_slug = self.book.make_chunk_slug(slug) -- 2.20.1 From f216a5268a7e03c010b6abaed1fb29d1e387fa1f Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 11 Feb 2025 15:31:45 +0100 Subject: [PATCH 02/11] fix for numbering --- src/redakcja/static/js/wiki/view_editor_wysiwyg.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/redakcja/static/js/wiki/view_editor_wysiwyg.js b/src/redakcja/static/js/wiki/view_editor_wysiwyg.js index 2e1c28d2..4a3cd6bd 100644 --- a/src/redakcja/static/js/wiki/view_editor_wysiwyg.js +++ b/src/redakcja/static/js/wiki/view_editor_wysiwyg.js @@ -951,6 +951,7 @@ let $e = $(e); if ($e.closest('[x-node="abstrakt"]').length) return; if ($e.closest('[x-node="nota_red"]').length) return; + if ($e.closest('[x-annotation-box="true"]').length) return; let node = $e.attr('x-node'); if (node == 'numeracja') { number = 0; -- 2.20.1 From fa491172e51c164fd620f73859788dfce2ebc9ac Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 19 Feb 2025 10:57:26 +0100 Subject: [PATCH 03/11] synchro --- src/documents/templates/documents/base.html | 1 - .../templates/documents/synchro.html | 169 ++++++++++++++---- src/documents/views.py | 105 ++++++----- 3 files changed, 189 insertions(+), 86 deletions(-) diff --git a/src/documents/templates/documents/base.html b/src/documents/templates/documents/base.html index 53ed63a2..9d7e3f7a 100644 --- a/src/documents/templates/documents/base.html +++ b/src/documents/templates/documents/base.html @@ -3,7 +3,6 @@ {% load static %} {% load documents %} {% load alerts %} - diff --git a/src/documents/templates/documents/synchro.html b/src/documents/templates/documents/synchro.html index bc44673e..346c33c4 100644 --- a/src/documents/templates/documents/synchro.html +++ b/src/documents/templates/documents/synchro.html @@ -3,47 +3,144 @@ {% 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 %} - -
-
- - +

Wskazówki synchronizacji dla: {{ book.title }}

+ + +
+ - {% for h, m in table %} - - - - - {% endfor %} + +
Nagłówek cięcia Audiobook
- {% if h %} - - {{ h.0 }} (linia {{ h.2 }}) - - {% else %} - — - {% endif %} - {{ m|default_if_none:'—' }}
+ + +
+ {% csrf_token %} + + +
+ +{% endblock %} + + +{% block add_js %} + {% endblock %} diff --git a/src/documents/views.py b/src/documents/views.py index 97d2ad6d..e87dc6db 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -5,6 +5,7 @@ from collections import defaultdict from copy import deepcopy from datetime import datetime, date, timedelta from itertools import zip_longest +import json import logging import os from urllib.parse import quote_plus, unquote, urlsplit, urlunsplit @@ -25,6 +26,7 @@ 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 lxml import etree from librarian import epubcheck from librarian.html import raw_printable_text @@ -770,14 +772,29 @@ def mark_final_completed(request): return render(request, 'documents/mark_final_completed.html') +@login_required 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) + if request.method == 'POST': + #hints = json.loads(request.POST.get('hints')) + chunk = book[0] + tree = etree.fromstring(chunk.head.materialize()) + m = tree.find('.//meta[@id="synchro"]') + if m is None: + rdf = tree.find('.//{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description') + m = etree.SubElement(rdf, 'meta', id="synchro") + m.tail = '\n' + m.text = request.POST.get('hints') + text = etree.tostring(tree, encoding='unicode') + chunk.commit(text, author=request.user, description='Synchronizacja') + return HttpResponseRedirect('') + + document = book.wldocument(librarian2=True, publishable=False) + 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'] @@ -792,59 +809,49 @@ def synchro(request, slug): 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) - + ) + split_other = ( + 'naglowek_czesc', + 'naglowek_akt', + 'naglowek_podrozdzial', + 'srodtytul', + ) + + headers = [] + headers_other = [] + master = document.tree.getroot()[-1] + for item in master: + if item.tag in split_on: + headers.append([ + item.tag, + raw_printable_text(item), + 0, + item.sourceline, + ]) + if item.tag in split_other: + headers_other.append([ + item.tag, + raw_printable_text(item), + 0, + item.sourceline, + ]) + + hints = [] + m = document.tree.find('.//meta[@id="synchro"]') + if m is not None: + try: + hints = json.loads(m.text) + except: + raise + pass return render(request, 'documents/synchro.html', { 'book': book, - 'documents': documents, 'headers': headers, + 'headers_other': headers_other, 'mp3': mp3, - 'length_ok': length_ok, - 'table': table, 'error': error, + 'hints': hints, }) -- 2.20.1 From 05cab4277ee54e18f8f03067f3b8031c0732d858 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 14 Mar 2025 09:04:29 +0100 Subject: [PATCH 04/11] update --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 68dab26a..f336baaa 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -10,7 +10,7 @@ python-slugify==8.0.1 python-docx==0.8.11 Wikidata==0.7 -librarian==24.1 +librarian==24.5.8 ## Django Django==4.1.9 -- 2.20.1 From 8da57c41af2d69702bbc23c7a64adc6f102d2bcd Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 1 Apr 2025 15:36:13 +0200 Subject: [PATCH 05/11] Minor editing improvements. --- src/redakcja/static/js/wiki/loader.js | 11 +++++ .../static/js/wiki/view_editor_wysiwyg.js | 9 ++-- .../templates/wiki/document_details_base.html | 2 +- src/wiki/templates/wiki/save_dialog.html | 45 ++++++++++--------- 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/redakcja/static/js/wiki/loader.js b/src/redakcja/static/js/wiki/loader.js index e9cf2b1a..adc2cb42 100644 --- a/src/redakcja/static/js/wiki/loader.js +++ b/src/redakcja/static/js/wiki/loader.js @@ -119,6 +119,17 @@ $(function() { CurrentDocument.active = new Date(); }); + $(window).keydown(function(e) { + if (e.ctrlKey || e.metaKey) { + switch (e.key) { + case 's': + e.preventDefault(); + $("#save-button").click(); + break; + } + } + }); + console.log("Fetching document's text"); $(document).bind('wlapi_document_changed', function(event, doc) { diff --git a/src/redakcja/static/js/wiki/view_editor_wysiwyg.js b/src/redakcja/static/js/wiki/view_editor_wysiwyg.js index 4a3cd6bd..3d4ca02c 100644 --- a/src/redakcja/static/js/wiki/view_editor_wysiwyg.js +++ b/src/redakcja/static/js/wiki/view_editor_wysiwyg.js @@ -110,7 +110,7 @@ success: function(text){ var t = $(text); tag.replaceWith(t); - openForEdit(t); + openForEdit(t, trim=false); }, error: function(){ tag.remove(); @@ -405,7 +405,7 @@ } /* open edition window for selected fragment */ - function openForEdit($origin){ + function openForEdit($origin, trim=true){ var $box = null // annotations overlay their sub box - not their own box // @@ -515,7 +515,10 @@ element: source, stripOuter: true, success: function(text){ - let ttext = $.trim(text); + let ttext = text; + if (trim) { + ttext = ttext.trim(); + } $('textarea', $overlay).val(ttext); setTimeout(function(){ diff --git a/src/wiki/templates/wiki/document_details_base.html b/src/wiki/templates/wiki/document_details_base.html index 88f837c6..2ae83a54 100644 --- a/src/wiki/templates/wiki/document_details_base.html +++ b/src/wiki/templates/wiki/document_details_base.html @@ -67,7 +67,7 @@ {% trans "Version" %}: {% trans "Unknown" %} {% if not readonly %} - + {% trans "Save attempt in progress" %} {% trans "There is a newer version of this document!" %} {% endif %} diff --git a/src/wiki/templates/wiki/save_dialog.html b/src/wiki/templates/wiki/save_dialog.html index b1330455..18295132 100644 --- a/src/wiki/templates/wiki/save_dialog.html +++ b/src/wiki/templates/wiki/save_dialog.html @@ -26,34 +26,39 @@ - {% else %} -

- {{ forms.text_save.stage_completed.label }}: - {{ forms.text_save.stage_completed }} - {{ forms.text_save.stage_completed.help_text }} - -

- {% if can_pubmark %} -

- {{ forms.text_save.publishable.label_tag }}: - {{ forms.text_save.publishable }} - {{ forms.text_save.publishable.help_text }} - -

{% endif %} +

+ +
+ + + + {% if request.user.is_authenticated %} +
+
+ {{ forms.text_save.stage_completed.label }}: + {{ forms.text_save.stage_completed }} + {{ forms.text_save.stage_completed.help_text }} + +
+ {% if can_pubmark %} +
+ {{ forms.text_save.publishable.label_tag }} + {{ forms.text_save.publishable }} + {{ forms.text_save.publishable.help_text }} + +
{% endif %} +
+ + {% endif %} +
{% for f in forms.text_save.hidden_fields %} {{ f }} {% endfor %} -

- -

- - -

-- 2.20.1 From 1cc3cb0514586ece78aa7b03bf19e83e7b3789a3 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 1 Apr 2025 15:37:12 +0200 Subject: [PATCH 06/11] add search option --- src/documents/api/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/documents/api/views.py b/src/documents/api/views.py index 36e886c2..751a9d41 100644 --- a/src/documents/api/views.py +++ b/src/documents/api/views.py @@ -24,7 +24,10 @@ class ChunkList(ListAPIView): queryset = models.Chunk.objects.all() serializer_class = serializers.ChunkSerializer filterset_fields = ['user', 'stage'] - search_fields = ['book__title'] + search_fields = [ + 'book__title', + '=book_slug', + ] def get_queryset(self): return models.Chunk.get_visible_for(self.request.user) -- 2.20.1 From 461c5c048f565ffbc0d9fad72f642c9de8704079 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 1 Apr 2025 16:15:27 +0200 Subject: [PATCH 07/11] Fix dialog actions on Enter --- src/redakcja/static/js/wiki/base.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/redakcja/static/js/wiki/base.js b/src/redakcja/static/js/wiki/base.js index ad0ca835..3ee92c4b 100644 --- a/src/redakcja/static/js/wiki/base.js +++ b/src/redakcja/static/js/wiki/base.js @@ -249,9 +249,7 @@ var self = this; /* bind buttons */ - $('button[data-ui-action]', self.$elem).click(function(event) { - event.preventDefault(); - + function dataUiAction(elem) { var action = $(this).attr('data-ui-action'); console.log("Button pressed, action: ", action); @@ -263,6 +261,15 @@ if(action == 'cancel') self.hide(); } + } + $('button[data-ui-action]', self.$elem).click(function(event) { + event.preventDefault(); + dataUiAction(this); + }).on('keydown'), function(event) { + if (event.key == 'Enter') { + event.preventDefault(); + dataUiAction(this); + } }); } -- 2.20.1 From 1ee716ea2b876762950786a9d9d2ba2f666530f9 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 15 Apr 2025 15:56:28 +0200 Subject: [PATCH 08/11] Source scan numbering --- src/sources/templates/sources/upload.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/sources/templates/sources/upload.html b/src/sources/templates/sources/upload.html index 39e64066..09847964 100644 --- a/src/sources/templates/sources/upload.html +++ b/src/sources/templates/sources/upload.html @@ -5,3 +5,21 @@ Skany źródła ładujemy w oryginalnej jakości. {% endblock %} + + +{% block add_css %} +{{ block.super }} + +{% endblock %} -- 2.20.1 From 8f049b683ba43e70018b1bd860f6c082b171ead5 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 5 May 2025 13:02:31 +0200 Subject: [PATCH 09/11] Remove br magic. --- src/redakcja/static/js/wiki/xslt.js | 2 +- src/wlxml/templates/wlxml/wl2html.xsl | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/redakcja/static/js/wiki/xslt.js b/src/redakcja/static/js/wiki/xslt.js index 99af3c35..922a3ba2 100644 --- a/src/redakcja/static/js/wiki/xslt.js +++ b/src/redakcja/static/js/wiki/xslt.js @@ -36,7 +36,7 @@ function withStylesheets(code_block, onError) function xml2html(options) { withStylesheets(function() { - var xml = options.xml.replace(/\/(\s+)/g, '
$1'); + var xml = options.xml.replace(/\/(\s+)/g, '<_n />$1'); xml = xml.replace(/([^a-zA-Z0-9ąćęłńóśźżĄĆĘŁŃÓŚŹŻ\s<>«»\\*_!,:;?&%."'=#()\/-]+)/g, '$1'); var parser = new DOMParser(); var serializer = new XMLSerializer(); diff --git a/src/wlxml/templates/wlxml/wl2html.xsl b/src/wlxml/templates/wlxml/wl2html.xsl index 9716e19f..c70286a0 100644 --- a/src/wlxml/templates/wlxml/wl2html.xsl +++ b/src/wlxml/templates/wlxml/wl2html.xsl @@ -81,16 +81,16 @@ - - + + - - - + + + + select="following-sibling::node()[count(preceding-sibling::_n) = $lnum+1]" /> @@ -106,7 +106,7 @@ - + @@ -114,17 +114,17 @@ - +
- +
- + @@ -143,7 +143,7 @@
{% endif %} - / + / {% if tags.span %} -- 2.20.1 From 0b1fc9f5cb0afc9d221653de39e02c094d1c01c8 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 5 May 2025 13:04:10 +0200 Subject: [PATCH 10/11] bugfix --- src/redakcja/static/js/wiki/base.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/redakcja/static/js/wiki/base.js b/src/redakcja/static/js/wiki/base.js index 3ee92c4b..574dd59b 100644 --- a/src/redakcja/static/js/wiki/base.js +++ b/src/redakcja/static/js/wiki/base.js @@ -250,7 +250,7 @@ /* bind buttons */ function dataUiAction(elem) { - var action = $(this).attr('data-ui-action'); + var action = $(elem).attr('data-ui-action'); console.log("Button pressed, action: ", action); try { @@ -265,7 +265,7 @@ $('button[data-ui-action]', self.$elem).click(function(event) { event.preventDefault(); dataUiAction(this); - }).on('keydown'), function(event) { + }).on('keydown', function(event) { if (event.key == 'Enter') { event.preventDefault(); dataUiAction(this); -- 2.20.1 From d27f7090b1e9a7909a9ec90302cd3bf732293139 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 16 Jun 2025 15:29:23 +0200 Subject: [PATCH 11/11] up --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index f336baaa..c8ac892d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -10,7 +10,7 @@ python-slugify==8.0.1 python-docx==0.8.11 Wikidata==0.7 -librarian==24.5.8 +librarian==24.5.9 ## Django Django==4.1.9 -- 2.20.1