Seasonal overlays
authorRadek Czajka <rczajka@rczajka.pl>
Fri, 8 May 2026 13:16:33 +0000 (15:16 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Fri, 8 May 2026 13:16:33 +0000 (15:16 +0200)
12 files changed:
src/annoy/migrations/0023_banner_video_alter_banner_place.py [new file with mode: 0644]
src/annoy/models.py
src/annoy/places.py
src/annoy/templates/annoy/banner_seasonal_overlay.html [new file with mode: 0644]
src/annoy/templates/annoy/checkout_header.html [new file with mode: 0644]
src/annoy/templatetags/annoy.py
src/catalogue/migrations/0058_alter_book_can_sell_mp3.py [new file with mode: 0644]
src/club/templates/club/donation_step1.html
src/club/templates/club/donation_step_base.html
src/wolnelektury/static/2022/styles/layout/_annoy.scss
src/wolnelektury/static/2022/styles/layout/_checkout.scss
src/wolnelektury/templates/base.html

diff --git a/src/annoy/migrations/0023_banner_video_alter_banner_place.py b/src/annoy/migrations/0023_banner_video_alter_banner_place.py
new file mode 100644 (file)
index 0000000..7ba8961
--- /dev/null
@@ -0,0 +1,23 @@
+# Generated by Django 4.0.8 on 2026-04-29 11:49
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('annoy', '0022_remove_banner_progress_remove_banner_target'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='banner',
+            name='video',
+            field=models.FileField(blank=True, upload_to='annoy/banners/', verbose_name='video'),
+        ),
+        migrations.AlterField(
+            model_name='banner',
+            name='place',
+            field=models.SlugField(choices=[('top', 'U góry wszystkich stron'), ('book-page', 'Strona książki'), ('book-page-center', 'Strona książki, środek'), ('book-text-intermission', 'Przerwa w treści książki'), ('book-fragment-list', 'Obok listy fragmentów książki'), ('blackout', 'Blackout'), ('crisis', 'Kryzysowa'), ('seasonal', 'Sezonowa'), ('seasonal-overlay', 'Sezonowa-overlay')], verbose_name='miejsce'),
+        ),
+    ]
index 7ef119e..c4f4ff0 100644 (file)
@@ -87,6 +87,7 @@ class Banner(models.Model):
     close_label = models.CharField('etykieta zamykania', max_length=255, blank=True)
     text = models.TextField('tekst')
     image = models.FileField('obraz', upload_to='annoy/banners/', blank=True)
+    video = models.FileField('video', upload_to='annoy/banners/', blank=True)
     url = models.CharField('URL', max_length=1024)
     priority = models.PositiveSmallIntegerField(
         'priorytet', default=0,
index 2fbd34c..ae7fe44 100644 (file)
@@ -14,6 +14,7 @@ PLACE_DEFINITIONS = [
         ('loud', 'Ostry'),
     )),
     ('seasonal', 'Sezonowa', False),
+    ('seasonal-overlay', 'Sezonowa-overlay', True),
 ]
 
 PLACE_CHOICES = [p[:2] for p in PLACE_DEFINITIONS]
diff --git a/src/annoy/templates/annoy/banner_seasonal_overlay.html b/src/annoy/templates/annoy/banner_seasonal_overlay.html
new file mode 100644 (file)
index 0000000..7ab86b2
--- /dev/null
@@ -0,0 +1,41 @@
+{% if banner %}
+<span class="annoy-banner-on"
+      data-target="#annoy-banner-{{ banner.id }}"
+      ></span>
+<div class="l-container t-relative">
+  <div class="
+              annoy-banner
+              annoy-banner_{{ banner.place }}
+              {% if banner.get_image %}with-image{% endif %}
+              {% if banner.video %}with-video{% endif %}
+              "
+        id="annoy-banner-{{ banner.id }}"
+       style="
+           {% if banner.text_color %}color: {{ banner.text_color }};{% endif %}
+           {% if banner.background_color %}background-color: {{ banner.background_color }};{% endif %}
+        ">
+    <div class="annoy-banner-inner">
+
+      {% if banner.get_image %}
+      <div>
+        <img src="{{ banner.get_image.url }}">
+       </div>
+      {% endif %}
+      {% if banner.video %}
+      <video src="{{ banner.video.url }}" controls></video>
+      {% endif %}
+      <div class="text">
+        {{ banner.get_text|safe }}
+        <a class="l-button l-button--default">{{ banner.action_label }}</a>
+      </div>
+
+      
+      <a class='annoy-banner-off annoy-banner-off_{{ banner.place }}  l-button l-button--default'>
+        <span class="c-hamburger"><span class="bar animate"></span></span>
+      </a>
+
+    </div>
+
+  </div>
+</div>
+{% endif %}
diff --git a/src/annoy/templates/annoy/checkout_header.html b/src/annoy/templates/annoy/checkout_header.html
new file mode 100644 (file)
index 0000000..225d3b5
--- /dev/null
@@ -0,0 +1,9 @@
+
+<div class="l-checkout__box__header__img l-checkout__box__header__real">
+  {% if banner.video %}
+  <video src="{{ banner.video.url }}" controls></video>
+  {% endif %}
+</div>
+<div class="l-checkout__box__header__content">
+  {{ banner.text|safe }}
+</div>
index 602fb3c..ac1b628 100644 (file)
@@ -53,3 +53,23 @@ def annoy_banner_seasonal(context):
         'banner': banners.first(),
         'closable': False,
     }
+
+@register.inclusion_tag('annoy/banner_seasonal_overlay.html', takes_context=True)
+def annoy_banner_seasonal_overlay(context):
+    banners = Banner.choice('seasonal-overlay', request=context['request'])
+    return {
+        'banner': banners.first(),
+    }
+
+
+@register.simple_tag(takes_context=True)
+def seasonal_overlay_exists(context):
+    return Banner.choice('seasonal-overlay', request=context['request'], exemptions=False).exists()
+
+
+@register.inclusion_tag('annoy/checkout_header.html', takes_context=True)
+def annoy_checkout_header(context):
+    banners = Banner.choice('seasonal-overlay', request=context['request'], exemptions=False)
+    return {
+        'banner': banners.first(),
+    }
diff --git a/src/catalogue/migrations/0058_alter_book_can_sell_mp3.py b/src/catalogue/migrations/0058_alter_book_can_sell_mp3.py
new file mode 100644 (file)
index 0000000..bd32041
--- /dev/null
@@ -0,0 +1,18 @@
+# Generated by Django 4.0.8 on 2026-04-29 11:49
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('catalogue', '0057_book_can_sell_mp3'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='book',
+            name='can_sell_mp3',
+            field=models.BooleanField(default=False, verbose_name='do sprzedaży mp3'),
+        ),
+    ]
index d01e693..4c7292f 100644 (file)
@@ -1,6 +1,16 @@
 {% extends 'club/donation_step_base.html' %}
+{% load annoy %}
 {% load chunks %}
 
+{% block donation-form-header %}
+{% seasonal_overlay_exists as e %}
+{% if e %}
+{% annoy_checkout_header %}
+{% else %}
+{{ block.super }}
+{% endif %}
+{% endblock %}
+
 {% block donation-step-content %}
   {% include "club/donation_step1_form.html" %}
 {% endblock %}
index 0c99d3c..e2cec7a 100644 (file)
 
     <div class="l-checkout__box">
       <div class="l-checkout__box__header">
+        {% block donation-form-header %}
         <div class="l-checkout__box__header__img"
              style="background-image: url({% block donation-jumbo-image %}{% static '2022/images/checkout-img-1.jpg' %}{% endblock %}">
           </div>
         <div class="l-checkout__box__header__content">
           {% chunk "donate-top" %}
         </div>
+        {% endblock %}
       </div>
       <div class="l-checkout__steps">
 
index f6b619a..18c8df8 100644 (file)
             justify-content: space-between;
         }
 }
+
+
+.t-relative {
+    position: relative;
+}
+.annoy-banner_seasonal-overlay {
+    display: none;
+    
+    background-color: #ffd430;
+    color: #083F4D;
+    border-radius: 0 0 10px 10px;
+    position: absolute;
+    z-index: 1000;
+    left: 16px;
+    right: 16px;
+    padding: 15px 20px;
+    margin-top: -10px;
+
+    &:before {
+        background: rgba(0,0,0,0);
+        height: 10px;
+        display: block;
+        content: "";
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        border-radius: 0 0 10px 10px;
+        box-shadow: 0px 10px 10px black;
+        z-index: 999;
+    }  
+    
+    .annoy-banner-inner {
+       display: flex;
+       flex-direction: column;
+       gap: 20px;
+       align-items: flex-start;
+       justify-content: space-between;
+
+        @include rwd($break-flow) {
+            flex-direction: row;
+        }
+        
+        .annoy-banner-off {
+            background: none;
+            border-color: transparent;
+
+            position: absolute;
+            top: 16px;
+            right: 16px;
+            padding: 12px 4px;
+        }
+        
+        video {
+            height: 240px;
+            width: 100%;
+            @include rwd($break-flow) {
+                height: 360px;
+                width: auto;
+            }
+        }
+
+        .text {
+            margin-right: 60px;
+            h1 {
+                font-size: 1.5em;
+                margin: 0 0 1em;
+                font-weight: bold;
+            }
+        
+           p {
+               margin: 1em 0;
+           }
+            .l-button {
+                display: inline-block;
+                margin-top: 1em;
+                padding: 12px 20px;
+            }
+        }
+        
+    }
+}
index 3b1ce06..135c653 100644 (file)
 }
 
 .l-checkout__box__header {
-  display: flex;
+    display: flex;
+    flex-direction: column;
   background: #083F4D;
 
+  @include rwd($break-flow) {
+      flex-direction: row;
+  }
+
   .l-checkout__box__header__img {
       display: none;
+      background: black;
       background-position: center;
       background-size: cover;
       @include rwd($break-flow) {
           display: block;
           width: 50%;
       }
-  }
-}
 
-.l-checkout__box__header__content h1 {
-  font-style: italic;
-  font-weight: 300;
-  font-size: 48px;
-  line-height: 55px;
-  letter-spacing: -0.02em;
-  color: #92BD39;
-  margin: 0;
+      &.l-checkout__box__header__real {
+          display: block;
+          width: auto;
+
+          video {
+              height: 200px;
+              width: 100%;
+              display: block;
+              @include rwd($break-flow) {
+                  height: 360px;
+                  width: auto;
+              }
+          }
+      }
+  }
 }
 
-.l-checkout__box__header__content p:first-of-type {
-  font-style: normal;
-  font-weight: 600;
-  font-size: 21.5px;
-  line-height: 140%;
-  letter-spacing: -0.01em;
-  color: #FFFFFF;
-  margin-top: 23px;
-}
+.l-checkout__box__header__content {
+    color: white;
+    padding: 32px 45px;
+
+    h1 {
+        font-style: italic;
+        font-weight: 300;
+        font-size: 48px;
+        line-height: 55px;
+        letter-spacing: -0.02em;
+        color: #92BD39;
+        margin: 0;
+    }
 
-.l-checkout__box__header__content p {
-  font-weight: normal;
-  font-size: 18px;
-  line-height: 150%;
-  color: #FFFFFF;
-  margin-top: 8px;
+    p {
+        font-weight: normal;
+        font-size: 18px;
+        line-height: 150%;
+        margin-top: 8px;
+
+        &:first-of-type {
+            font-weight: 600;
+            font-size: 21.5px;
+            line-height: 140%;
+            letter-spacing: -0.01em;
+            margin-top: 23px;
+        }
+    }
 }
 
-.l-checkout__box__header__content {
-  padding: 32px 45px;
-}
 
 //Steps
 .l-checkout__steps {
index cf921fb..2f7b99f 100644 (file)
@@ -40,6 +40,7 @@
     {% endif %}
 
     {% annoy_banner_seasonal %}
+    {% annoy_banner_seasonal_overlay %}
       
     {% block global-content %}
       <div class="l-container l-breadcrumb-container">