sorl-thumbnail==12.8.0
# home-brewed & dependencies
-librarian==23.10
+librarian==24.1
# celery tasks
celery[redis]==5.2.7
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')]);
});
# 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
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."""
return found
@staticmethod
- def transform(wldoc):
+ def transform(wldoc, book):
"""Transforms an librarian.WLDocument into an librarian.OutputFile.
"""
raise NotImplemented()
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)
for_parents = False
@staticmethod
- def transform(wldoc):
+ def transform(wldoc, book):
return wldoc.as_text()
ZIP = 'wolnelektury_pl_fb2'
@staticmethod
- def transform(wldoc):
+ def transform(wldoc, book):
return wldoc.as_fb2()
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):
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)
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)
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'))
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
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()
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()
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()
directory = 'cover_ebookpoint'
@staticmethod
- def transform(wldoc):
+ def transform(wldoc, book):
from librarian.cover import EbookpointCover
return EbookpointCover(wldoc.book_info).output_file()
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
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)
@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:
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()
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:
{% 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 %}
</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"
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)
})
--- /dev/null
+# 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'),
+ ),
+ ]
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)
--- /dev/null
+# 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'),
+ ),
+ ]
"""
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)
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'
<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">
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,
})
border-radius: 0 0 5px 5px;
margin: 0 auto;
display: flex;
+ gap: 10px;
align-items: center;
justify-content: space-between;
position: relative;
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;
.annoy-banner-inner {
padding: 0;
margin: 10vh 10vw 20vh 10vw;
+ max-height: 70vh;
flex-direction: row;
overflow-y: unset;
/*!*/
+@import "annoy";
@import "navigation";
@import "header";
@import "main";