From f5129e7c47fa5fcf0a20f04249b90afcbc54cb9c Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 13 Dec 2019 13:31:28 +0100 Subject: [PATCH 1/1] Annoy! --- src/annoy/__init__.py | 0 src/annoy/admin.py | 24 ++ src/annoy/apps.py | 5 + src/annoy/migrations/0001_initial.py | 64 ++++++ .../migrations/0002_auto_20191211_1320.py | 23 ++ .../migrations/0003_auto_20191211_1511.py | 18 ++ .../migrations/0004_auto_20191211_1512.py | 23 ++ .../migrations/0005_auto_20191211_1617.py | 70 ++++++ .../migrations/0006_auto_20191213_1328.py | 23 ++ src/annoy/migrations/__init__.py | 0 src/annoy/models.py | 82 +++++++ src/annoy/places.py | 16 ++ src/annoy/static/annoy/banner.js | 32 +++ src/annoy/static/annoy/banner.scss | 213 ++++++++++++++++++ src/annoy/static/annoy/book_text.js | 51 +++++ src/annoy/static/annoy/book_text.scss | 15 ++ src/annoy/templates/annoy/banner.html | 28 +++ src/annoy/templates/annoy/banners.html | 3 + src/annoy/templatetags/annoy.py | 23 ++ src/annoy/tests.py | 3 + src/annoy/translation.py | 15 ++ src/annoy/utils.py | 9 + src/annoy/views.py | 3 + .../templates/catalogue/book_detail.html | 3 + .../templates/catalogue/book_fragments.html | 4 + .../templates/catalogue/book_text.html | 21 ++ .../templates/catalogue/viewer_base.html | 3 +- src/catalogue/views.py | 3 + src/club/urls.py | 13 +- src/wolnelektury/settings/apps.py | 1 + src/wolnelektury/settings/static.py | 10 +- src/wolnelektury/static/css/annoy.css | 69 ------ src/wolnelektury/static/js/annoy.js | 30 --- src/wolnelektury/static/scss/main/cite.scss | 2 + .../static/scss/main/fragment.scss | 6 +- src/wolnelektury/templates/annoy.html | 25 -- .../templates/base/superbase.html | 4 +- 37 files changed, 800 insertions(+), 137 deletions(-) create mode 100644 src/annoy/__init__.py create mode 100644 src/annoy/admin.py create mode 100644 src/annoy/apps.py create mode 100644 src/annoy/migrations/0001_initial.py create mode 100644 src/annoy/migrations/0002_auto_20191211_1320.py create mode 100644 src/annoy/migrations/0003_auto_20191211_1511.py create mode 100644 src/annoy/migrations/0004_auto_20191211_1512.py create mode 100644 src/annoy/migrations/0005_auto_20191211_1617.py create mode 100644 src/annoy/migrations/0006_auto_20191213_1328.py create mode 100644 src/annoy/migrations/__init__.py create mode 100644 src/annoy/models.py create mode 100644 src/annoy/places.py create mode 100644 src/annoy/static/annoy/banner.js create mode 100644 src/annoy/static/annoy/banner.scss create mode 100644 src/annoy/static/annoy/book_text.js create mode 100644 src/annoy/static/annoy/book_text.scss create mode 100644 src/annoy/templates/annoy/banner.html create mode 100644 src/annoy/templates/annoy/banners.html create mode 100644 src/annoy/templatetags/annoy.py create mode 100644 src/annoy/tests.py create mode 100644 src/annoy/translation.py create mode 100644 src/annoy/utils.py create mode 100644 src/annoy/views.py delete mode 100755 src/wolnelektury/static/css/annoy.css delete mode 100644 src/wolnelektury/static/js/annoy.js delete mode 100644 src/wolnelektury/templates/annoy.html diff --git a/src/annoy/__init__.py b/src/annoy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/annoy/admin.py b/src/annoy/admin.py new file mode 100644 index 000000000..7a82d6867 --- /dev/null +++ b/src/annoy/admin.py @@ -0,0 +1,24 @@ +from django.contrib import admin +from django import forms +from modeltranslation.admin import TranslationAdmin +from . import models + + +class BannerAdmin(TranslationAdmin): + list_display = ['place', 'text', 'priority', 'since', 'until', 'show_members', 'staff_preview'] + + +admin.site.register(models.Banner, BannerAdmin) + + +class DynamicTextInsertTextInline(admin.TabularInline): + model = models.DynamicTextInsertText + fields = ['text', 'image', 'background_color', 'text_color'] + + +class DynamicTextInsertAdmin(admin.ModelAdmin): + list_display = ['paragraphs'] + inlines = [DynamicTextInsertTextInline] + + +admin.site.register(models.DynamicTextInsert, DynamicTextInsertAdmin) diff --git a/src/annoy/apps.py b/src/annoy/apps.py new file mode 100644 index 000000000..213a4e98e --- /dev/null +++ b/src/annoy/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class AnnoyConfig(AppConfig): + name = 'annoy' diff --git a/src/annoy/migrations/0001_initial.py b/src/annoy/migrations/0001_initial.py new file mode 100644 index 000000000..d5b091ea6 --- /dev/null +++ b/src/annoy/migrations/0001_initial.py @@ -0,0 +1,64 @@ +# Generated by Django 2.2.6 on 2019-12-11 11:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Banner', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('place', models.SlugField(choices=[('top', 'Top of all pages.'), ('book-page', 'Book page'), ('book-text-intermission', 'Book text intermission'), ('fragment-list', 'Next to list of book fragments.')])), + ('text', models.TextField()), + ('text_de', models.TextField(null=True)), + ('text_en', models.TextField(null=True)), + ('text_es', models.TextField(null=True)), + ('text_fr', models.TextField(null=True)), + ('text_it', models.TextField(null=True)), + ('text_lt', models.TextField(null=True)), + ('text_pl', models.TextField(null=True)), + ('text_ru', models.TextField(null=True)), + ('text_uk', models.TextField(null=True)), + ('url', models.CharField(max_length=1024)), + ('priority', models.PositiveSmallIntegerField(default=0)), + ('since', models.DateTimeField(blank=True, null=True)), + ('until', models.DateTimeField(blank=True, null=True)), + ('show_members', models.BooleanField(default=False)), + ], + options={ + 'verbose_name': 'banner', + 'verbose_name_plural': 'banners', + 'ordering': ('place', '-priority'), + }, + ), + migrations.CreateModel( + name='DynamicTextInsert', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('paragraphs', models.IntegerField(verbose_name='pararaphs')), + ('text', models.TextField(verbose_name='text')), + ('text_de', models.TextField(null=True, verbose_name='text')), + ('text_en', models.TextField(null=True, verbose_name='text')), + ('text_es', models.TextField(null=True, verbose_name='text')), + ('text_fr', models.TextField(null=True, verbose_name='text')), + ('text_it', models.TextField(null=True, verbose_name='text')), + ('text_lt', models.TextField(null=True, verbose_name='text')), + ('text_pl', models.TextField(null=True, verbose_name='text')), + ('text_ru', models.TextField(null=True, verbose_name='text')), + ('text_uk', models.TextField(null=True, verbose_name='text')), + ('url', models.CharField(max_length=1024)), + ], + options={ + 'verbose_name': 'dynamic insert', + 'verbose_name_plural': 'dynamic inserts', + 'ordering': ('paragraphs',), + }, + ), + ] diff --git a/src/annoy/migrations/0002_auto_20191211_1320.py b/src/annoy/migrations/0002_auto_20191211_1320.py new file mode 100644 index 000000000..8d23a1f56 --- /dev/null +++ b/src/annoy/migrations/0002_auto_20191211_1320.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.6 on 2019-12-11 12:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('annoy', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='banner', + name='open_label', + field=models.CharField(blank=True, max_length=255), + ), + migrations.AlterField( + model_name='banner', + name='place', + field=models.SlugField(choices=[('top', 'Top of all pages.'), ('book-page', 'Book page'), ('book-text-intermission', 'Book text intermission'), ('book-fragment-list', 'Next to list of book fragments.')]), + ), + ] diff --git a/src/annoy/migrations/0003_auto_20191211_1511.py b/src/annoy/migrations/0003_auto_20191211_1511.py new file mode 100644 index 000000000..daa3f9729 --- /dev/null +++ b/src/annoy/migrations/0003_auto_20191211_1511.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.6 on 2019-12-11 14:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('annoy', '0002_auto_20191211_1320'), + ] + + operations = [ + migrations.AlterField( + model_name='banner', + name='place', + field=models.SlugField(choices=[('top', 'Top of all pages.'), ('book-page', 'Book page'), ('book-text-intermission', 'Book text intermission'), ('book-fragment-list', 'Next to list of book fragments.'), ('blackout', 'Blackout')]), + ), + ] diff --git a/src/annoy/migrations/0004_auto_20191211_1512.py b/src/annoy/migrations/0004_auto_20191211_1512.py new file mode 100644 index 000000000..0e57edf10 --- /dev/null +++ b/src/annoy/migrations/0004_auto_20191211_1512.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.6 on 2019-12-11 14:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('annoy', '0003_auto_20191211_1511'), + ] + + operations = [ + migrations.AddField( + model_name='banner', + name='action_label', + field=models.CharField(blank=True, max_length=255), + ), + migrations.AddField( + model_name='banner', + name='close_label', + field=models.CharField(blank=True, max_length=255), + ), + ] diff --git a/src/annoy/migrations/0005_auto_20191211_1617.py b/src/annoy/migrations/0005_auto_20191211_1617.py new file mode 100644 index 000000000..5fa9b95df --- /dev/null +++ b/src/annoy/migrations/0005_auto_20191211_1617.py @@ -0,0 +1,70 @@ +# Generated by Django 2.2.6 on 2019-12-11 15:17 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('annoy', '0004_auto_20191211_1512'), + ] + + operations = [ + migrations.RemoveField( + model_name='dynamictextinsert', + name='text', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_de', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_en', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_es', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_fr', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_it', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_lt', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_pl', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_ru', + ), + migrations.RemoveField( + model_name='dynamictextinsert', + name='text_uk', + ), + migrations.AlterField( + model_name='banner', + name='action_label', + field=models.CharField(blank=True, help_text='', max_length=255), + ), + migrations.CreateModel( + name='DynamicTextInsertText', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('background_color', models.CharField(blank=True, max_length=10)), + ('text_color', models.CharField(blank=True, max_length=10)), + ('text', models.TextField(verbose_name='text')), + ('image', models.FileField(blank=True, upload_to='')), + ('insert', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='annoy.DynamicTextInsert')), + ], + ), + ] diff --git a/src/annoy/migrations/0006_auto_20191213_1328.py b/src/annoy/migrations/0006_auto_20191213_1328.py new file mode 100644 index 000000000..acafafeb2 --- /dev/null +++ b/src/annoy/migrations/0006_auto_20191213_1328.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.6 on 2019-12-13 12:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('annoy', '0005_auto_20191211_1617'), + ] + + operations = [ + migrations.AddField( + model_name='banner', + name='staff_preview', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='banner', + name='action_label', + field=models.CharField(blank=True, help_text='', max_length=255), + ), + ] diff --git a/src/annoy/migrations/__init__.py b/src/annoy/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/annoy/models.py b/src/annoy/models.py new file mode 100644 index 000000000..26b0136c7 --- /dev/null +++ b/src/annoy/models.py @@ -0,0 +1,82 @@ +from django.apps import apps +from django.conf import settings +from django.db import models +from django.utils.translation import ugettext_lazy as _ +from django.utils.timezone import now +from .places import PLACES, PLACE_CHOICES + + +class Banner(models.Model): + place = models.SlugField(choices=PLACE_CHOICES) + action_label = models.CharField( + max_length=255, blank=True, + help_text=_('') + ) + open_label = models.CharField(max_length=255, blank=True) + close_label = models.CharField(max_length=255, blank=True) + text = models.TextField() + url = models.CharField(max_length=1024) + priority = models.PositiveSmallIntegerField(default=0) + since = models.DateTimeField(null=True, blank=True) + until = models.DateTimeField(null=True, blank=True) + show_members = models.BooleanField(default=False) + staff_preview = models.BooleanField(default=False) + + class Meta: + verbose_name = _('banner') + verbose_name_plural = _('banners') + ordering = ('place', '-priority',) + + def __str__(self): + return self.text + + @classmethod + def choice(cls, place, request): + Membership = apps.get_model('club', 'Membership') + + if hasattr(request, 'annoy_banner_exempt'): + return cls.objects.none() + + if settings.DEBUG: + assert place in PLACES, "Banner place `{}` must be defined in annoy.places.".format(place) + + n = now() + banners = cls.objects.filter( + place=place + ).exclude( + since__gt=n + ).exclude( + until__lt=n + ).order_by('-priority', '?') + + if not request.user.is_staff: + banners = banners.filter(staff_preview=False) + + if request: + if Membership.is_active_for(request.user): + banners = banners.filter(show_members=True) + return banners + + +class DynamicTextInsert(models.Model): + paragraphs = models.IntegerField(_('pararaphs')) + url = models.CharField(max_length=1024) + + class Meta: + verbose_name = _('dynamic insert') + verbose_name_plural = _('dynamic inserts') + ordering = ('paragraphs', ) + + def __str__(self): + return str(self.paragraphs) + + def choose(self): + return self.dynamictextinserttext_set.order_by('?').first() + + +class DynamicTextInsertText(models.Model): + insert = models.ForeignKey(DynamicTextInsert, models.CASCADE) + background_color = models.CharField(max_length=10, blank=True) + text_color = models.CharField(max_length=10, blank=True) + text = models.TextField(_('text')) + image = models.FileField(blank=True) diff --git a/src/annoy/places.py b/src/annoy/places.py new file mode 100644 index 000000000..93b22e44e --- /dev/null +++ b/src/annoy/places.py @@ -0,0 +1,16 @@ +from django.utils.translation import ugettext_lazy as _ + +PLACE_DEFINITIONS = [ + ('top', _('Top of all pages.'), True), + ('book-page', _('Book page'), False), + ('book-text-intermission', _('Book text intermission'), False), + ('book-fragment-list', _('Next to list of book fragments.'), False), + ('blackout', _('Blackout'), True), +] + +PLACE_CHOICES = [p[:2] for p in PLACE_DEFINITIONS] + +PLACES = { + p[0]: p[2] + for p in PLACE_DEFINITIONS +} diff --git a/src/annoy/static/annoy/banner.js b/src/annoy/static/annoy/banner.js new file mode 100644 index 000000000..ee4561341 --- /dev/null +++ b/src/annoy/static/annoy/banner.js @@ -0,0 +1,32 @@ +(function($) { + $(function() { + + $(".annoy-banner-on").each(function() { + var $on = $(this); + var tag = 'annoyed' + $on.attr('data-target'); + var $target = $($on.attr('data-target')); + var $off = $('.annoy-banner-off', $target); + + $on.click(function(e) { + e.preventDefault(); + $target.slideDown('fast'); + $on.hide(); + if (Modernizr.localstorage) localStorage.removeItem(tag); + }); + + $off.click(function() { + $target.slideUp('fast'); + $on.show(); + if (Modernizr.localstorage) localStorage[tag] = true; + }); + + if (Modernizr.localstorage) { + if (!localStorage[tag]) { + $on.hide(); + $target.show(); + } + } + }); + + }); +})(jQuery); diff --git a/src/annoy/static/annoy/banner.scss b/src/annoy/static/annoy/banner.scss new file mode 100644 index 000000000..33fd48199 --- /dev/null +++ b/src/annoy/static/annoy/banner.scss @@ -0,0 +1,213 @@ +.annoy-banner { + background: orange; + + p { + text-align: center; + } + + a { + color: black; + display: block; + padding: 1em 2em; + } +} + + +.annoy-banner-off { + cursor: pointer; +} + +.annoy-banner_top { + display: none; + + p { + margin: 0; + font-size: 2em; + } + + .annoy-banner-off { + padding: .5em 1em .5em; + width: 1em; + text-align:center; + font-family: Arial, sans-serif; + display: block; + + border-radius: 0 0 0 1em; + position: absolute; + top: 0; + right: 0; + color: black; + font-size: 13px; + } +} + +.annoy-banner-on_top { + font-size: 13px; + line-height: 1.15em; + + background: orange; + z-index: 99; + font-family: Arial, sans-serif; + display: block; + padding: .1em 1em; + text-align:center; + border-radius: 0 0 0 1em; + position: absolute; + top: 0; + right: 0; + color: black; +} + + +.annoy-banner_book-page { + margin-top: 30px; + font-size: 2em; + + p { + margin: 0; + } +} + + +.annoy-banner_book-fragment-list { + margin-right: 2em; +} + + + +.annoy-banner_blackout { + display: none; + + position: fixed; + z-index: 100000; + left: 0; + right: 0; + top: 0; + bottom: 0; + background: black; + color: white; + font-size: 16pt; + line-height: 26pt; + padding: 0; + + .annoy-banner-inner { + padding: 0 40% 0 15%; + height: 100%; + overflow-y: scroll; + padding-top: 20vh; + padding-bottom: 2em; + width: 101vw; + box-sizing: border-box; + } + + p { + text-align: left; + } + + a { + color: white; + position: absolute; + right: 10%; + width: 25%; + border-radius: 24px; + text-align: center; + box-sizing: border-box; + padding: 1em; + + &.annoy-banner-off { + bottom: 20vh; + background: #666; + border-radius: auto 100%; + font-size: .75em; + padding: .5em; + width: 20%; + margin-right: 2.5%; + } + + &.action { + bottom: 33vh; + background: #018189; + color: white; + border-radius: auto 100%; + padding: 1.5em 1em; + } + } + + @media screen and (max-height: 1000px) { + .annoy-banner-inner { + padding-top: 5vh; + } + } + + @media screen and (max-width: 1280px) { + .annoy-banner-inner { + padding-left: 5%; + padding-right: 50%; + padding-left: 5%; + padding-right: 50%; + } + + a { + right: 5%; + width: 40%; + + &.annoy-banner-off { + width: 40%; + margin-right: 0%; + } + } + + } + @media screen and (max-width: 1024px) { + font-size: 14pt; + line-height: 21pt; + } + @media screen and (max-height: 820px) { + .annoy-banner-inner { + padding-top: 5vh; + } + } + @media screen and (max-width: 820px) and (max-height: 820px) { + a.action { + bottom: 20vh; + } + a.annoy-banner-off { + bottom: 5vh; + } + } + @media screen and (max-height: 400px) { + a.action { + bottom: 30vh; + } + } + + +} +.annoy-banner-on_blackout { + position: fixed; + z-index: 9999; + bottom: 0; + right: 0; + background: black; + color: white; + border-radius: 1em 0 0 0; + padding: .1em 1em; +} + + + +.dynamic-insert.with-image { + min-height: 120px; + padding: 0; + + a { + position: relative; + .text { + } + img { + position: absolute; + top: 10px; + right: 10px; + } + } +} diff --git a/src/annoy/static/annoy/book_text.js b/src/annoy/static/annoy/book_text.js new file mode 100644 index 000000000..267d6e1bd --- /dev/null +++ b/src/annoy/static/annoy/book_text.js @@ -0,0 +1,51 @@ +(function($) { + $(function() { + + + var fold = $(window).scrollTop() + $(window).height(); + + var inserts = []; + $("#annoy-stubs .dynamic-insert").each(function() {inserts.push($(this));}); + + var $intermissions = $("#annoy-stubs .annoy-banner_book-text-intermission"); + if ($intermissions.length) { + var which = 0; + $("#book-text a + h2").each(function(i, e) { + console.log(i); + if (i) { + $($intermissions[which]).clone().insertBefore($(this)).show(); + which = (which + 1) % $intermissions.length; + } + }); + + if ($("#footnotes").length) { + $($intermissions[which]).clone().insertBefore($("#footnotes")).show(); + } else { + $($intermissions[which]).clone().appendTo($("#book-text")).show(); + } + }; + + if (inserts) { + var underFold = false; + var counter = 0; + $(".paragraph, .stanza").each(function() { + var p = $(this); + if (!underFold) { + if (p.offset().top > fold) { + underFold = true; + } + } + if (underFold) { + if (inserts[0].attr('data-paragraphs') == counter) { + insert = inserts.shift(); + insert.insertBefore(p); + } + counter += 1; + } + return inserts.length > 0; + }); + }; + + + }); +})(jQuery); diff --git a/src/annoy/static/annoy/book_text.scss b/src/annoy/static/annoy/book_text.scss new file mode 100644 index 000000000..37c83ef70 --- /dev/null +++ b/src/annoy/static/annoy/book_text.scss @@ -0,0 +1,15 @@ +.dynamic-insert, .intermission { + margin: 2em 0; + padding: 2em; + background: orange; + + a { + display: block; + color: black; + } +} + + +#annoy-stubs { + display: none; +} diff --git a/src/annoy/templates/annoy/banner.html b/src/annoy/templates/annoy/banner.html new file mode 100644 index 000000000..3f54eb26e --- /dev/null +++ b/src/annoy/templates/annoy/banner.html @@ -0,0 +1,28 @@ +{% if banner %} + {% if closable %} + + {{ banner.open_label }} + + {% endif %} +
+
+ {% if banner.action_label %} + {{ banner.text|safe|linebreaks }} + + {{ banner.action_label }} + + {% else %} + + {{ banner.text|safe|linebreaks }} + + {% endif %} + {% if closable %} + {{ banner.close_label|default:"x" }} + {% endif %} +
+
+ +{% endif %} diff --git a/src/annoy/templates/annoy/banners.html b/src/annoy/templates/annoy/banners.html new file mode 100644 index 000000000..7de539e0d --- /dev/null +++ b/src/annoy/templates/annoy/banners.html @@ -0,0 +1,3 @@ +{% for banner in banners %} + {% include "annoy/banner.html" %} +{% endfor %} diff --git a/src/annoy/templatetags/annoy.py b/src/annoy/templatetags/annoy.py new file mode 100644 index 000000000..21f1bb85e --- /dev/null +++ b/src/annoy/templatetags/annoy.py @@ -0,0 +1,23 @@ +from django import template +from ..models import Banner +from ..places import PLACES + + +register = template.Library() + + +@register.inclusion_tag('annoy/banner.html', takes_context=True) +def annoy_banner(context, place): + banners = Banner.choice(place, request=context['request']) + return { + 'banner': banners.first(), + 'closable': PLACES.get(place, False), + } + + +@register.inclusion_tag('annoy/banners.html', takes_context=True) +def annoy_banners(context, place): + return { + 'banners': Banner.choice(place, request=context['request']), + 'closable': PLACES.get(place, False), + } diff --git a/src/annoy/tests.py b/src/annoy/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/src/annoy/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/src/annoy/translation.py b/src/annoy/translation.py new file mode 100644 index 000000000..eb17ada17 --- /dev/null +++ b/src/annoy/translation.py @@ -0,0 +1,15 @@ +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from modeltranslation.translator import translator, TranslationOptions +from . import models + + +class BannerTranslationOptions(TranslationOptions): + fields = ('text',) + + + +translator.register(models.Banner, BannerTranslationOptions) + + diff --git a/src/annoy/utils.py b/src/annoy/utils.py new file mode 100644 index 000000000..07a1a63cc --- /dev/null +++ b/src/annoy/utils.py @@ -0,0 +1,9 @@ +from functools import wraps + + +def banner_exempt(view): + @wraps(view) + def wrapped(request, *args, **kwargs): + request.annoy_banner_exempt = True + return view(request, *args, **kwargs) + return wrapped diff --git a/src/annoy/views.py b/src/annoy/views.py new file mode 100644 index 000000000..91ea44a21 --- /dev/null +++ b/src/annoy/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/src/catalogue/templates/catalogue/book_detail.html b/src/catalogue/templates/catalogue/book_detail.html index de1b45a1b..6e875bd4e 100644 --- a/src/catalogue/templates/catalogue/book_detail.html +++ b/src/catalogue/templates/catalogue/book_detail.html @@ -2,6 +2,7 @@ {% load i18n %} {% load catalogue_tags %} {% load build_absolute_uri from fnp_common %} +{% load annoy_banner from annoy %} {% load cache %} {% block titleextra %}{{ book.pretty_title }}{% endblock %} @@ -27,6 +28,8 @@ {% endif %} + {% annoy_banner 'book-page' %} +

{% trans "See also" %}:

{% related_books book taken=book.other_versions|length %} diff --git a/src/catalogue/templates/catalogue/book_fragments.html b/src/catalogue/templates/catalogue/book_fragments.html index 7696c149f..4bcb30e01 100644 --- a/src/catalogue/templates/catalogue/book_fragments.html +++ b/src/catalogue/templates/catalogue/book_fragments.html @@ -1,6 +1,7 @@ {% extends "base/base.html" %} {% load i18n %} {% load work_list from catalogue_tags %} +{% load annoy_banner from annoy %} {% block titleextra %}{% trans "Theme" %} {{ theme }} {% trans "in work " %} {{ book }}{% endblock %} @@ -12,6 +13,9 @@ {{ theme }}
{% trans "in work " %} {{ book }} + + {% annoy_banner 'book-fragment-list' %} +
diff --git a/src/catalogue/templates/catalogue/book_text.html b/src/catalogue/templates/catalogue/book_text.html index a1c0b23f9..c08f76cff 100644 --- a/src/catalogue/templates/catalogue/book_text.html +++ b/src/catalogue/templates/catalogue/book_text.html @@ -1,7 +1,9 @@ {% extends "catalogue/viewer_base.html" %} {% load i18n %} {% load catalogue_tags %} +{% load chunks %} {% load thumbnail %} +{% load annoy_banners from annoy %} {% block title %}{{ book.pretty_title }}{% endblock %} @@ -109,4 +111,23 @@
{% include 'catalogue/book_short.html' %}
+ +
+ {% annoy_banners 'book-text-intermission' %} + + {% for insert in inserts %} + {% with text=insert.choose %} + + {% endwith %} + {% endfor %} +
{% endblock footer %} diff --git a/src/catalogue/templates/catalogue/viewer_base.html b/src/catalogue/templates/catalogue/viewer_base.html index a975d67af..6df862c16 100644 --- a/src/catalogue/templates/catalogue/viewer_base.html +++ b/src/catalogue/templates/catalogue/viewer_base.html @@ -3,6 +3,7 @@ {% load static from static %} {% load pipeline %} {% load piwik_tags %} +{% load annoy_banner from annoy %} @@ -13,7 +14,7 @@ {% block extrahead %}{% endblock %} - {% include "annoy.html" %} + {% annoy_banner 'top' %}