Missing logos.
authorRadek Czajka <rczajka@rczajka.pl>
Wed, 31 Jan 2024 07:44:46 +0000 (08:44 +0100)
committerRadek Czajka <rczajka@rczajka.pl>
Wed, 31 Jan 2024 07:44:46 +0000 (08:44 +0100)
17 files changed:
requirements/requirements.txt
src/annoy/static/annoy/banner.js
src/catalogue/fields.py
src/catalogue/forms.py
src/catalogue/models/book.py
src/catalogue/templates/catalogue/book_info.html
src/catalogue/templates/catalogue/book_text.html
src/catalogue/views.py
src/club/migrations/0045_alter_payuorder_pos_id.py [new file with mode: 0644]
src/club/payu/models.py
src/funding/migrations/0011_alter_funding_customer_ip_alter_funding_notify_key_and_more.py [new file with mode: 0644]
src/funding/models.py
src/references/templates/references/map.html
src/references/views.py
src/wolnelektury/static/2022/styles/components/_media.scss
src/wolnelektury/static/2022/styles/layout/_annoy.scss
src/wolnelektury/static/2022/styles/layout/_module.scss

index acae076..0fa6143 100644 (file)
@@ -39,7 +39,7 @@ mutagen==1.45.1
 sorl-thumbnail==12.8.0
 
 # home-brewed & dependencies
-librarian==23.10
+librarian==24.1
 
 # celery tasks
 celery[redis]==5.2.7
index 74a7292..791741a 100644 (file)
                 e.preventDefault();
                 $target.slideDown('fast');
                 $on.hide();
-                if (Modernizr.localstorage) localStorage.removeItem(tag);
+                localStorage.removeItem(tag);
                 _paq.push(['trackEvent', 'banner', 'banner-unhide', $target.attr('id')]);
             });
 
             $off.click(function() {
                 $target.slideUp('fast');
                 $on.show();
-                if (Modernizr.localstorage) localStorage[tag] = true;
+                localStorage[tag] = true;
                 _paq.push(['trackEvent', 'banner', 'banner-hide', $target.attr('id')]);
             });
 
index 646ab15..087fe0d 100644 (file)
@@ -1,15 +1,19 @@
 # This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
 #
+import io
 import os
 import pkg_resources
 import random
+import time
+from urllib.request import urlopen
 from django.apps import apps
 from django.conf import settings
 from django.core.files import File
 from django.db import models
 from django.db.models.fields.files import FieldFile
 from django.utils.deconstruct import deconstructible
+from librarian.cover import make_cover
 from catalogue.constants import LANGUAGES_3TO2
 from catalogue.utils import absolute_url, remove_zip, truncate_html_words, gallery_path, gallery_url
 from waiter.utils import clear_cache
@@ -31,6 +35,25 @@ class UploadToPath(object):
         return isinstance(other, type(self)) and other.path == self.path
 
 
+def get_make_cover(book):
+    extra = book.get_extra_info_json()
+    cover_logo = extra.get('logo_mono', extra.get('logo'))
+    if cover_logo:
+        while True:
+            try:
+                cover_logo = io.BytesIO(urlopen(cover_logo, timeout=3).read())
+            except:
+                time.sleep(2)
+            else:
+                break
+    
+    def mc(*args, **kwargs):
+        if cover_logo:
+            kwargs['cover_logo'] = cover_logo
+        return make_cover(*args, **kwargs)
+    return mc
+    
+
 class EbookFieldFile(FieldFile):
     """Represents contents of an ebook file field."""
 
@@ -172,7 +195,7 @@ class EbookField(models.FileField):
         return found
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         """Transforms an librarian.WLDocument into an librarian.OutputFile.
         """
         raise NotImplemented()
@@ -185,6 +208,7 @@ class EbookField(models.FileField):
         book = fieldfile.instance
         out = self.transform(
             book.wldocument2() if self.librarian2_api else book.wldocument(),
+            book,
         )
         with open(out.get_filename(), 'rb') as f:
             fieldfile.save(None, File(f), save=False)
@@ -207,7 +231,7 @@ class TxtField(EbookField):
     for_parents = False
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         return wldoc.as_text()
 
 
@@ -217,7 +241,7 @@ class Fb2Field(EbookField):
     ZIP = 'wolnelektury_pl_fb2'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         return wldoc.as_fb2()
 
 
@@ -226,9 +250,10 @@ class PdfField(EbookField):
     ZIP = 'wolnelektury_pl_pdf'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         return wldoc.as_pdf(
-            morefloats=settings.LIBRARIAN_PDF_MOREFLOATS, cover=True,
+            morefloats=settings.LIBRARIAN_PDF_MOREFLOATS,
+            cover=get_make_cover(book),
             base_url=absolute_url(gallery_url(wldoc.book_info.url.slug)), customizations=['notoc'])
 
     def build(self, fieldfile):
@@ -242,12 +267,13 @@ class EpubField(EbookField):
     ZIP = 'wolnelektury_pl_epub'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         from librarian.builders import EpubBuilder
         MediaInsertSet = apps.get_model('annoy', 'MediaInsertSet')
         return EpubBuilder(
                 base_url='file://' + os.path.abspath(gallery_path(wldoc.meta.url.slug)) + '/',
-                fundraising=MediaInsertSet.get_texts_for('epub')
+                fundraising=MediaInsertSet.get_texts_for('epub'),
+                cover=get_make_cover(book),
             ).build(wldoc)
 
 
@@ -257,12 +283,13 @@ class MobiField(EbookField):
     ZIP = 'wolnelektury_pl_mobi'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         from librarian.builders import MobiBuilder
         MediaInsertSet = apps.get_model('annoy', 'MediaInsertSet')
         return MobiBuilder(
                 base_url='file://' + os.path.abspath(gallery_path(wldoc.meta.url.slug)) + '/',
-                fundraising=MediaInsertSet.get_texts_for('mobi')
+                fundraising=MediaInsertSet.get_texts_for('mobi'),
+                cover=get_make_cover(book),
             ).build(wldoc)
 
 
@@ -359,7 +386,7 @@ class HtmlField(EbookField):
         return False
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         # ugly, but we can't use wldoc.book_info here
         from librarian import DCNS
         url_elem = wldoc.edoc.getroot().find('.//' + DCNS('identifier.url'))
@@ -378,8 +405,8 @@ class CoverField(EbookField):
     directory = 'cover'
 
     @staticmethod
-    def transform(wldoc):
-        return wldoc.as_cover()
+    def transform(wldoc, book):
+        return get_make_cover(book)(wldoc.book_info, width=360).output_file()
 
     def set_file_permissions(self, fieldfile):
         pass
@@ -389,16 +416,15 @@ class CoverCleanField(CoverField):
     directory = 'cover_clean'
 
     @staticmethod
-    def transform(wldoc):
-        from librarian.covers.marquise import MarquiseCover
-        return MarquiseCover(wldoc.book_info, width=360).output_file()
+    def transform(wldoc, book):
+        return get_make_cover(book)(wldoc.book_info, width=360).output_file()
 
 
 class CoverThumbField(CoverField):
     directory = 'cover_thumb'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         from librarian.cover import WLCover
         return WLCover(wldoc.book_info, height=193).output_file()
 
@@ -407,7 +433,7 @@ class CoverApiThumbField(CoverField):
     directory = 'cover_api_thumb'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         from librarian.cover import WLNoBoxCover
         return WLNoBoxCover(wldoc.book_info, height=500).output_file()
 
@@ -416,7 +442,7 @@ class SimpleCoverField(CoverField):
     directory = 'cover_simple'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         from librarian.cover import WLNoBoxCover
         return WLNoBoxCover(wldoc.book_info, height=1000).output_file()
 
@@ -425,6 +451,6 @@ class CoverEbookpointField(CoverField):
     directory = 'cover_ebookpoint'
 
     @staticmethod
-    def transform(wldoc):
+    def transform(wldoc, book):
         from librarian.cover import EbookpointCover
         return EbookpointCover(wldoc.book_info).output_file()
index 100f794..055800e 100644 (file)
@@ -17,6 +17,8 @@ class BookImportForm(forms.Form):
     gallery_url = forms.CharField(required=False)
     days = forms.IntegerField(required=False)
     hidden = forms.BooleanField(required=False)
+    logo = forms.CharField(required=False)
+    logo_mono = forms.CharField(required=False)
 
     def clean(self):
         from django.core.files.base import ContentFile
@@ -34,6 +36,8 @@ class BookImportForm(forms.Form):
                                   remote_gallery_url=self.cleaned_data['gallery_url'],
                                   days=self.cleaned_data['days'],
                                   findable=not self.cleaned_data['hidden'],
+                                  logo=self.cleaned_data['logo'],
+                                  logo_mono=self.cleaned_data['logo_mono'],
                                   **kwargs)
 
 
index 411476a..b14269f 100644 (file)
@@ -594,7 +594,7 @@ class Book(models.Model):
 
     @classmethod
     def from_text_and_meta(cls, raw_file, book_info, overwrite=False, dont_build=None, search_index=True,
-                           remote_gallery_url=None, days=0, findable=True):
+                           remote_gallery_url=None, days=0, findable=True, logo=None, logo_mono=None):
         from catalogue import tasks
 
         if dont_build is None:
@@ -641,7 +641,12 @@ class Book(models.Model):
             book.common_slug = book_info.variant_of.slug
         else:
             book.common_slug = book.slug
-        book.extra_info = json.dumps(book_info.to_dict())
+        extra = book_info.to_dict()
+        if logo:
+            extra['logo'] = logo
+        if logo_mono:
+            extra['logo_mono'] = logo_mono
+        book.extra_info = json.dumps(extra)
         book.load_abstract()
         book.load_toc()
         book.save()
@@ -729,8 +734,12 @@ class Book(models.Model):
             else:
                 entity, entity_created = Entity.objects.get_or_create(uri=uri)
                 if entity_created:
-                    entity.populate()
-                    entity.save()
+                    try:
+                        entity.populate()
+                    except:
+                        pass
+                    else:
+                        entity.save()
                 ref, ref_created = entity.reference_set.get_or_create(book=self)
                 refs[uri] = ref
                 if not ref_created:
index 3da38b2..424d759 100644 (file)
@@ -1,5 +1,6 @@
 {% load i18n %}
 {% load catalogue_tags %}
+{% load thumbnail %}
 
 {% with extra_info=book.get_extra_info_json %}
   <p>
     <p>{{ extra_info.description }}</p>
   {% endif %}
 
+  {% if extra_info.logo %}
+    {% thumbnail extra_info.logo '300x200' as th %}
+    <img src="{{ th.url }}" style="width: 300px; max-width: 100%;">
+  {% endthumbnail %}
+  {% endif %}
+
   {% if extra_info.editor or extra_info.technical_editor %}
     <p>
       {% if is_picture %}
index d9474b5..041a07a 100644 (file)
     </a>
   </li>
 
+  {% if extra_info.logo_mono %}
+  {% thumbnail extra_info.logo_mono '200x200' as th %}
+    <img src="{{ th.url }}" style="width: 100px; padding: 10px;">
+  {% endthumbnail %}
+  {% endif %}
+
   <a href="#" class="settings-switch" id="settings-line-numbers"
      data-setting="always-hide-line-numbers"><span>{% trans "Numeracja" %}</span></a>
   <a href="#" class="settings-switch" id="settings-themes"
index 62ba2be..af4d1e3 100644 (file)
@@ -546,6 +546,7 @@ def book_text(request, slug):
 
     return render(request, 'catalogue/book_text.html', {
         'book': book,
+        'extra_info': book.get_extra_info_json(),
         'book_text': book_text,
         'inserts': DynamicTextInsert.get_all(request)
     })
diff --git a/src/club/migrations/0045_alter_payuorder_pos_id.py b/src/club/migrations/0045_alter_payuorder_pos_id.py
new file mode 100644 (file)
index 0000000..024b1d4
--- /dev/null
@@ -0,0 +1,18 @@
+# Generated by Django 4.0.8 on 2024-01-31 07:41
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('club', '0044_alter_ambassador_options_alter_club_options_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='payuorder',
+            name='pos_id',
+            field=models.CharField(blank=True, max_length=255, verbose_name='POS id'),
+        ),
+    ]
index d50ee8b..af38448 100644 (file)
@@ -25,7 +25,7 @@ class CardToken(models.Model):
 
 
 class Order(models.Model):
-    pos_id = models.CharField('POS id', max_length=255)   # TODO: redundant?
+    pos_id = models.CharField('POS id', max_length=255, blank=True)   # TODO: redundant?
     customer_ip = models.GenericIPAddressField('adres IP klienta')
     order_id = models.CharField('ID zamówienia', max_length=255, blank=True)
 
diff --git a/src/funding/migrations/0011_alter_funding_customer_ip_alter_funding_notify_key_and_more.py b/src/funding/migrations/0011_alter_funding_customer_ip_alter_funding_notify_key_and_more.py
new file mode 100644 (file)
index 0000000..59825ee
--- /dev/null
@@ -0,0 +1,28 @@
+# Generated by Django 4.0.8 on 2024-01-31 07:41
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('funding', '0010_alter_funding_options_alter_offer_options_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='funding',
+            name='customer_ip',
+            field=models.GenericIPAddressField(blank=True, null=True, verbose_name='adres IP'),
+        ),
+        migrations.AlterField(
+            model_name='funding',
+            name='notify_key',
+            field=models.CharField(blank=True, max_length=32),
+        ),
+        migrations.AlterField(
+            model_name='funding',
+            name='pos_id',
+            field=models.CharField(blank=True, max_length=255, verbose_name='POS id'),
+        ),
+    ]
index 620255a..23afa3c 100644 (file)
@@ -262,7 +262,7 @@ class Funding(club.payu.models.Order):
 
     """
     offer = models.ForeignKey(Offer, models.PROTECT, verbose_name='zbiórka')
-    customer_ip = models.GenericIPAddressField('adres IP', null=True)
+    customer_ip = models.GenericIPAddressField('adres IP', null=True, blank=True)
     
     name = models.CharField('nazwa', max_length=127, blank=True)
     email = models.EmailField('e-mail', blank=True, db_index=True)
@@ -271,7 +271,7 @@ class Funding(club.payu.models.Order):
     perks = models.ManyToManyField(Perk, verbose_name='prezenty', blank=True)
     language_code = models.CharField(max_length=2, null=True, blank=True)
     notifications = models.BooleanField('powiadomienia', default=True, db_index=True)
-    notify_key = models.CharField(max_length=32)
+    notify_key = models.CharField(max_length=32, blank=True)
 
     class Meta:
         verbose_name = 'wpłata'
index 3b266a1..c067f49 100644 (file)
@@ -15,7 +15,7 @@
   <link rel="stylesheet" type="text/css" media="all" href="{% static 'contrib/leaflet.markercluster-1.4.1/MarkerCluster.css' %}">
   <link rel="stylesheet" type="text/css" media="all" href="{% static 'contrib/leaflet.markercluster-1.4.1/MarkerCluster.Default.css' %}">
   <meta property="og:type" content="website">
-  <meta property="og:title" content="Wakacje z Wolnymi Lekturami">
+  <meta property="og:title" content="Mapa Wolnych Lektur">
   <meta property="og:image" content="{% static 'references/preview.png' %}">
   <meta property="og:image:alt" content="Mapa miejsc w książkach na Wolnych Lekturach">
   <meta property="og:image:width" content="1200">
index 3c12c8f..7e0e357 100644 (file)
@@ -8,7 +8,7 @@ from . import models
 
 def pin_map(request):
     return render(request, 'references/map.html', {
-        'title': 'Wakacje',
+        'title': 'Mapa Wolnych Lektur',
         'entities': models.Entity.objects.exclude(lat=None).exclude(lon=None),
         'funding_no_show_current': True,
     })
index ebeb7aa..c4af4eb 100644 (file)
@@ -52,6 +52,7 @@
   border-radius: 0 0 5px 5px;
   margin: 0 auto;
   display: flex;
+  gap: 10px;
   align-items: center;
   justify-content: space-between;
   position: relative;
index 432ee4d..f0f0636 100644 (file)
@@ -14,6 +14,7 @@
     background: linear-gradient(180deg, rgba(0,0,0,1) 90%, rgba(0,0, 0,.5) 100%);
 
     .annoy-banner-inner {
+        max-height: 100vh;
         overflow-y: auto;
         padding: 0 0 30px 0;
         display: flex;
@@ -55,6 +56,7 @@
         .annoy-banner-inner {
             padding: 0;
             margin: 10vh 10vw 20vh 10vw;
+            max-height: 70vh;
             flex-direction: row;
             overflow-y: unset;