From de4bd61ee1bb8fb2aa04d9925c4f9ff882d9ba91 Mon Sep 17 00:00:00 2001
From: OndraRehounek <ondra.rehounek@seznam.cz>
Date: Thu, 18 Nov 2021 13:35:17 +0100
Subject: [PATCH] district: Pirate center page

---
 district/blocks.py                            |  30 ++++++
 .../migrations/0015_auto_20211118_1240.py     | 102 ++++++++++++++++++
 ...0016_districtcenterpage_sidebar_content.py |  79 ++++++++++++++
 district/models.py                            |  57 ++++++++++
 .../district/blocks/address_block.html        |  21 ++++
 .../district/blocks/contact_block.html        |   7 ++
 .../district/district_center_page.html        |  48 +++++++++
 .../include/small_calendar_snippet.html       |  53 +++++++++
 .../calendar_current_events_snippet.html      |  79 ++++++++------
 shared/templates/shared/followus_snippet.html |   4 +-
 .../shared/followus_snippet_column.html       |  13 +++
 11 files changed, 460 insertions(+), 33 deletions(-)
 create mode 100644 district/migrations/0015_auto_20211118_1240.py
 create mode 100644 district/migrations/0016_districtcenterpage_sidebar_content.py
 create mode 100644 district/templates/district/blocks/address_block.html
 create mode 100644 district/templates/district/blocks/contact_block.html
 create mode 100644 district/templates/district/district_center_page.html
 create mode 100644 district/templates/district/include/small_calendar_snippet.html
 create mode 100644 shared/templates/shared/followus_snippet_column.html

diff --git a/district/blocks.py b/district/blocks.py
index b78a03da..6b5ac2a0 100644
--- a/district/blocks.py
+++ b/district/blocks.py
@@ -5,10 +5,40 @@ from wagtail.core.blocks import (
     PageChooserBlock,
     StructBlock,
     TextBlock,
+    URLBlock,
 )
 from wagtail.images.blocks import ImageChooserBlock
 
 
+class AddressBlock(StructBlock):
+    title = CharBlock(label="Titulek", required=True)
+    embed_map = URLBlock(
+        label="Odkaz na embed mapku",
+        required=False,
+        help_text="Hodnota 'src' v <iframe>",
+    )
+    address = TextBlock(label="Adresa", required=True)
+    address_info = TextBlock(label="Info k adrese", required=False)
+
+    class Meta:
+        template = "district/blocks/address_block.html"
+        icon = "home"
+        label = "Adresa"
+
+
+class ContactBlock(StructBlock):
+    title = CharBlock(label="Titulek", required=True)
+    contact_list = ListBlock(
+        PageChooserBlock(label="Osoba", page_type=["district.DistrictPersonPage"]),
+        label="List kontaktů",
+    )
+
+    class Meta:
+        template = "district/blocks/contact_block.html"
+        icon = "mail"
+        label = "Kontakt"
+
+
 class HomepageHeaderBlock(StructBlock):
     title = CharBlock(label="Titulek", required=True)
     subtitle = CharBlock(label="Podtitulek", required=False)
diff --git a/district/migrations/0015_auto_20211118_1240.py b/district/migrations/0015_auto_20211118_1240.py
new file mode 100644
index 00000000..652ceabd
--- /dev/null
+++ b/district/migrations/0015_auto_20211118_1240.py
@@ -0,0 +1,102 @@
+# Generated by Django 3.2.8 on 2021-11-18 11:40
+
+import django.db.models.deletion
+import wagtail.core.fields
+import wagtailmetadata.models
+from django.db import migrations, models
+
+import shared.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("wagtailimages", "0023_add_choose_permissions"),
+        ("wagtailcore", "0062_comment_models_and_pagesubscription"),
+        ("calendar_utils", "0002_auto_20200523_0243"),
+        ("district", "0014_districthomepage_fallback_image"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="districtarticlepage",
+            name="author_page",
+            field=models.ForeignKey(
+                blank=True,
+                null=True,
+                on_delete=django.db.models.deletion.SET_NULL,
+                to="district.districtpersonpage",
+            ),
+        ),
+        migrations.CreateModel(
+            name="DistrictCenterPage",
+            fields=[
+                (
+                    "page_ptr",
+                    models.OneToOneField(
+                        auto_created=True,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        parent_link=True,
+                        primary_key=True,
+                        serialize=False,
+                        to="wagtailcore.page",
+                    ),
+                ),
+                (
+                    "calendar_url",
+                    models.URLField(
+                        blank=True,
+                        null=True,
+                        verbose_name="URL kalendáře ve formátu iCal",
+                    ),
+                ),
+                (
+                    "perex",
+                    models.TextField(blank=True, null=True, verbose_name="Perex"),
+                ),
+                (
+                    "text",
+                    wagtail.core.fields.RichTextField(null=True, verbose_name="Text"),
+                ),
+                (
+                    "background_photo",
+                    models.ForeignKey(
+                        blank=True,
+                        null=True,
+                        on_delete=django.db.models.deletion.PROTECT,
+                        related_name="+",
+                        to="wagtailimages.image",
+                    ),
+                ),
+                (
+                    "calendar",
+                    models.ForeignKey(
+                        blank=True,
+                        null=True,
+                        on_delete=django.db.models.deletion.PROTECT,
+                        to="calendar_utils.calendar",
+                    ),
+                ),
+                (
+                    "search_image",
+                    models.ForeignKey(
+                        blank=True,
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name="+",
+                        to="wagtailimages.image",
+                        verbose_name="Search image",
+                    ),
+                ),
+            ],
+            options={
+                "verbose_name": "Stránka pirátského centra",
+            },
+            bases=(
+                shared.models.SubpageMixin,
+                wagtailmetadata.models.WagtailImageMetadataMixin,
+                "wagtailcore.page",
+                models.Model,
+            ),
+        ),
+    ]
diff --git a/district/migrations/0016_districtcenterpage_sidebar_content.py b/district/migrations/0016_districtcenterpage_sidebar_content.py
new file mode 100644
index 00000000..429ae1df
--- /dev/null
+++ b/district/migrations/0016_districtcenterpage_sidebar_content.py
@@ -0,0 +1,79 @@
+# Generated by Django 3.2.8 on 2021-11-18 12:29
+
+import wagtail.core.blocks
+import wagtail.core.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("district", "0015_auto_20211118_1240"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="districtcenterpage",
+            name="sidebar_content",
+            field=wagtail.core.fields.StreamField(
+                [
+                    (
+                        "address",
+                        wagtail.core.blocks.StructBlock(
+                            [
+                                (
+                                    "title",
+                                    wagtail.core.blocks.CharBlock(
+                                        label="Titulek", required=True
+                                    ),
+                                ),
+                                (
+                                    "embed_map",
+                                    wagtail.core.blocks.URLBlock(
+                                        label="Odkaz na embed mapku", required=False
+                                    ),
+                                ),
+                                (
+                                    "address",
+                                    wagtail.core.blocks.TextBlock(
+                                        label="Adresa", required=True
+                                    ),
+                                ),
+                                (
+                                    "address_info",
+                                    wagtail.core.blocks.TextBlock(
+                                        label="Info k adrese", required=False
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                    (
+                        "contact",
+                        wagtail.core.blocks.StructBlock(
+                            [
+                                (
+                                    "title",
+                                    wagtail.core.blocks.CharBlock(
+                                        label="Titulek", required=True
+                                    ),
+                                ),
+                                (
+                                    "contact_list",
+                                    wagtail.core.blocks.ListBlock(
+                                        wagtail.core.blocks.PageChooserBlock(
+                                            label="Osoba",
+                                            page_type=["district.DistrictPersonPage"],
+                                        ),
+                                        label="List kontaktů",
+                                    ),
+                                ),
+                            ]
+                        ),
+                    ),
+                ],
+                blank=True,
+                verbose_name="Obsah bočního panelu",
+            ),
+        ),
+    ]
diff --git a/district/models.py b/district/models.py
index 09d18f35..52dca013 100644
--- a/district/models.py
+++ b/district/models.py
@@ -23,6 +23,8 @@ from shared.models import ArticleMixin, Person, SubpageMixin
 from uniweb.constants import RICH_TEXT_FEATURES
 
 from .blocks import (
+    AddressBlock,
+    ContactBlock,
     HomepageHeaderBlock,
     PeopleGroupListBlock,
     RedmineProgramBlock,
@@ -151,6 +153,7 @@ class DistrictHomePage(MetadataPageMixin, CalendarMixin, Page):
 
     subpage_types = [
         "district.DistrictArticlesPage",
+        "district.DistrictCenterPage",
         "district.DistrictContactPage",
         "district.DistrictPeoplePage",
         "district.DistrictProgramPage",
@@ -565,3 +568,57 @@ class DistrictProgramPage(SubpageMixin, MetadataPageMixin, Page):
 
     class Meta:
         verbose_name = "Program"
+
+
+class DistrictCenterPage(CalendarMixin, SubpageMixin, MetadataPageMixin, Page):
+    ### FIELDS
+
+    perex = models.TextField("Perex", blank=True, null=True)
+    background_photo = models.ForeignKey(
+        "wagtailimages.Image",
+        on_delete=models.PROTECT,
+        blank=True,
+        null=True,
+        related_name="+",
+    )
+    text = RichTextField("Text", null=True)
+    sidebar_content = StreamField(
+        [("address", AddressBlock()), ("contact", ContactBlock())],
+        verbose_name="Obsah bočního panelu",
+        blank=True,
+    )
+
+    ### PANELS
+
+    content_panels = Page.content_panels + [
+        FieldPanel("perex"),
+        ImageChooserPanel("background_photo"),
+        FieldPanel("text"),
+        FieldPanel("calendar_url"),
+        StreamFieldPanel("sidebar_content"),
+    ]
+
+    ### RELATIONS
+
+    parent_page_types = ["district.DistrictHomePage"]
+    subpage_types = []
+
+    ### OTHERS
+
+    class Meta:
+        verbose_name = "Stránka pirátského centra"
+
+    def get_background_photo(self):
+        """
+        Vrací background_photo pro pozadí na stránce, pokud není nastaveno,
+        vezme falbback z homepage
+        """
+        return (
+            self.background_photo
+            if self.background_photo
+            else self.root_page.fallback_image
+        )
+
+    @property
+    def has_calendar(self):
+        return self.calendar_id is not None
diff --git a/district/templates/district/blocks/address_block.html b/district/templates/district/blocks/address_block.html
new file mode 100644
index 00000000..b2d5d89f
--- /dev/null
+++ b/district/templates/district/blocks/address_block.html
@@ -0,0 +1,21 @@
+<h2 class="head-heavy-sm mb-2">
+  {{ self.title }}
+</h2>
+
+<iframe
+  src="{{ self.embed_map }}"
+  width="100%" height="300" id="mapa-mobile" frameborder="0" style="border:0;" allowfullscreen="" aria-hidden="false"
+  tabindex="0"
+></iframe>
+
+<p>
+  {{ self.address | linebreaks }}
+</p>
+
+{% if self.address_info %}
+  <p>
+    <small>
+      {{ self.address_info }}
+    </small>
+  </p>
+{% endif %}
diff --git a/district/templates/district/blocks/contact_block.html b/district/templates/district/blocks/contact_block.html
new file mode 100644
index 00000000..c6903c22
--- /dev/null
+++ b/district/templates/district/blocks/contact_block.html
@@ -0,0 +1,7 @@
+<h2 class="head-heavy-sm mb-2">
+  {{ self.title }}
+</h2>
+
+{% for person_page in self.contact_list %}
+  {% include "shared/person_badge_snippet.html" %}
+{% endfor %}
diff --git a/district/templates/district/district_center_page.html b/district/templates/district/district_center_page.html
new file mode 100644
index 00000000..ca9969ec
--- /dev/null
+++ b/district/templates/district/district_center_page.html
@@ -0,0 +1,48 @@
+{% extends "district/base.html" %}
+{% load wagtailcore_tags wagtailimages_tags shared_filters %}
+
+{% block subheader %}
+  {% image page.get_background_photo width-1920 as bg_img %}
+  <aside class="hero hero--image py-16 " style="--image-url: url({{ bg_img.url }})">
+    <div class="container container--default">
+      <h1 class="head-alt-md md:head-alt-lg max-w-2xl">
+        {{ page.title }}
+      </h1>
+      <h2 class="head-xs mt-2">
+        {{ page.subtitle }}
+      </h2>
+    </div>
+  </aside>
+{% endblock %}
+
+{% block content %}
+  <div class="container container--default pt-8 lg:pb-16">
+    <article>
+      <div class="lg:flex lg:space-x-8 xl:space-x-16">
+        <div class="lg:w-3/5 xl:w-2/3">
+          <div class="content-block">
+            {{ page.text | richtext }}
+          </div>
+          {% include "district/include/small_calendar_snippet.html" %}
+        </div>
+        <div class="pt-8 lg:w-2/5 xl:w-1/3 lg:pt-0">
+          <div class="lg:card lg:elevation-10">
+            <div class="lg:card__body">
+              <div class="content-block">
+                {% for block in page.sidebar_content %}
+                  {% include_block block %}
+                  {% if not forloop.last %}
+                    <hr>
+                  {% endif %}
+                {% endfor %}
+              </div>
+            </div>
+          </div>
+
+          {% include "shared/followus_snippet_column.html" %}
+        </div>
+      </div>
+    </article>
+  </div>
+
+{% endblock %}
diff --git a/district/templates/district/include/small_calendar_snippet.html b/district/templates/district/include/small_calendar_snippet.html
new file mode 100644
index 00000000..60757687
--- /dev/null
+++ b/district/templates/district/include/small_calendar_snippet.html
@@ -0,0 +1,53 @@
+{% if page.has_calendar %}
+  <h2 class="head-heavy-sm mb-4 mt-4">
+    Kalendář akcí
+  </h2>
+  <div class="mb-4">
+    {% for event in page.root_page.calendar.current_events %}
+      <div class="grid grid-cols-12 items-center calendar-table-row calendar-table-row--standalone">
+        <div class="col-span-2 text-orange-300 head-alt-md calendar-table-row__col">
+          <span>{{ event.begin|date:"j." }}</span>
+        </div>
+        <div class="col-span-8 grid grid-cols-3 calendar-table-row__col">
+          <div class="col-span-3 md:col-span-1">
+            <strong class="block">{{ event.begin|date:"l j. E"|capfirst }}</strong>
+            <p class="font-light text-sm mt-1">{{ event.duration }}</p></div>
+          <div class="col-span-3 md:col-span-2 mt-4 md:mt-0">
+                <span class="font-bold block">
+                  {{ event.name }}
+                </span>
+            {% if event.description %}
+              <p class="font-light text-sm mt-1">{{ event.description | safe }}</p>
+            {% endif %}
+          </div>
+        </div>
+        <div class="col-span-2 text-center font-light calendar-table-row__col">
+          {% if event.location and 'jitsi.pirati' in event.location %}
+            <a href="{{ event.location }}" class="icon-link">
+              <i aria-hidden="true" class="ico--link text-violet-300 mr-1"></i>
+              <span>Jitsi URL</span>
+            </a>
+          {% elif event.location %}
+            <a href="https://maps.google.com/maps?q={{ event.location }}" class="icon-link">
+              <i aria-hidden="true" class="ico--location text-violet-300 mr-1"></i>
+              <span>Mapa</span>
+            </a>
+          {% endif %}
+        </div>
+      </div>
+    {% empty %}
+      <div class="content-block">
+        <p>Žádné události.</p>
+      </div>
+    {% endfor %}
+  </div>
+
+  {#  <button class="btn btn--icon btn--orange-300 btn--hoveractive btn--fullwidth md:btn--autowidth">#}
+  {#    <div class="btn__body-wrap">#}
+  {#      <div class="btn__body ">Další akce</div>#}
+  {#      <div class="btn__icon ">#}
+  {#        <i class="ico--chevron-right"></i>#}
+  {#      </div>#}
+  {#    </div>#}
+  {#  </button> TODO? #}
+{% endif %}
diff --git a/shared/templates/shared/calendar_current_events_snippet.html b/shared/templates/shared/calendar_current_events_snippet.html
index ad780032..3bd9aa85 100644
--- a/shared/templates/shared/calendar_current_events_snippet.html
+++ b/shared/templates/shared/calendar_current_events_snippet.html
@@ -1,39 +1,56 @@
 <div class="container container--default">
   {% if page.root_page.has_calendar %}
-    {% for event in page.root_page.calendar.current_events %}
-      <div class="grid grid-cols-12 items-center calendar-table-row calendar-table-row--standalone">
-        <div class="col-span-2 text-blue-200 head-alt-md calendar-table-row__col">
-          <span>{{ event.begin|date:"j." }}</span>
-        </div>
-        <div class="col-span-8 grid grid-cols-3 calendar-table-row__col">
-          <div class="col-span-3 md:col-span-1">
-            <strong class="block">{{ event.begin|date:"l j. E"|capfirst }}</strong>
-            <p class="font-light text-sm mt-1">{{ event.duration }}</p>
+    <div class="calendar grid grid-cols-4">
+      <div class="col-span-4 xl:col-span-1">
+        <aside class="banner bg-orange-300 text-white h-full"><i class="ico--calendar banner__icon"></i>
+          <div class="banner__body"><h1 class="head-alt-md banner__cta">Kalendář</h1>
+            <button class="btn btn--white btn--fullwidth sm:btn--autowidth mt-8">
+              <div class="btn__body">Zobrazit další</div>
+            </button>
           </div>
-          <div class="col-span-3 md:col-span-2 mt-4 md:mt-0">
-            <strong class="block">{{ event.name }}</strong>
-            {% if event.description %}
-              <p class="font-light text-sm mt-1">{{ event.description | safe }}</p>
-            {% endif %}
-            {% if event.location %}
-              <p class="font-light text-sm mt-1">{{ event.location }}</p>
-            {% endif %}
-          </div>
-        </div>
-        <div class="col-span-2 text-center font-light calendar-table-row__col">
-          {% if event.location %}
-            <a href="https://maps.google.com/maps?q={{ event.location }}" class="icon-link">
-              <i class="ico--location text-violet-300 mr-1" aria-hidden="true"></i>
-              <span>Mapa</span>
-            </a>
-          {% endif %}
-        </div>
+        </aside>
       </div>
-    {% empty %}
-      <div class="content-block">
-        <p>Žádné události.</p>
+      <div class="col-span-4 xl:col-span-3">
+        {% for event in page.root_page.calendar.current_events %}
+          <div class="grid grid-cols-12 items-center calendar-table-row">
+            <div class="col-span-2 text-orange-300 head-alt-md calendar-table-row__col">
+              <span>{{ event.begin|date:"j." }}</span>
+            </div>
+            <div class="col-span-8 grid grid-cols-3 col-gap-4 calendar-table-row__col calendar-table-row__col--norborder">
+              <div class="col-span-3 md:col-span-1">
+                <strong class="block">{{ event.begin|date:"l j. E"|capfirst }}</strong>
+                <p class="font-light text-sm mt-1">{{ event.duration }}</p></div>
+              <div class="col-span-3 md:col-span-2 mt-4 md:mt-0">
+                <span class="font-bold block">
+                  {{ event.name }}
+                </span>
+                {% if event.description %}
+                  <p class="font-light text-sm mt-1">{{ event.description | safe }}</p>
+                {% endif %}
+              </div>
+            </div>
+            <div class="col-span-2 text-center font-light calendar-table-row__col">
+              {% if event.location and 'jitsi.pirati' in event.location %}
+                <a href="{{ event.location }}" class="icon-link">
+                  <i aria-hidden="true" class="ico--link text-violet-300 mr-1"></i>
+{#                  <i aria-hidden="true" class="ico--jitsi text-violet-300 mr-1"></i> TODO requires latest styleguide version #}
+                  <span>Jitsi URL</span>
+                </a>
+              {% elif event.location %}
+                <a href="https://maps.google.com/maps?q={{ event.location }}" class="icon-link">
+                  <i aria-hidden="true" class="ico--location text-violet-300 mr-1"></i>
+                  <span>Mapa</span>
+                </a>
+              {% endif %}
+            </div>
+          </div>
+        {% empty %}
+          <div class="content-block">
+            <p>Žádné události.</p>
+          </div>
+        {% endfor %}
       </div>
-    {% endfor %}
+    </div>
   {% else %}
     <div class="content-block">
       <p>Žádné události.</p>
diff --git a/shared/templates/shared/followus_snippet.html b/shared/templates/shared/followus_snippet.html
index 59181100..a7e2b73e 100644
--- a/shared/templates/shared/followus_snippet.html
+++ b/shared/templates/shared/followus_snippet.html
@@ -1,11 +1,11 @@
 <div class="flex flex-col lg:flex-row lg:space-x-8">
-  <a href="{{ page.facebook }}"
+  <a href="{% firstof page.facebook page.root_page.facebook %}"
      class="super-button bg-brands-facebook text-white container-padding--zero lg:container-padding--auto lg:w-1/2 m-2">
     <span class="super-button__body">Sledujte nás na Facebooku</span>
     <i class="super-button__icon ico--facebook"></i>
   </a>
 
-  <a href="{{ page.forum }}"
+  <a href="{% firstof page.forum page.root_page.forum %}"
      class="super-button bg-black text-white container-padding--zero lg:container-padding--auto lg:w-1/2 m-2">
     <span class="super-button__body">Sledujte naše fórum</span>
     <i class="super-button__icon ico--bubbles"></i>
diff --git a/shared/templates/shared/followus_snippet_column.html b/shared/templates/shared/followus_snippet_column.html
new file mode 100644
index 00000000..fead8e54
--- /dev/null
+++ b/shared/templates/shared/followus_snippet_column.html
@@ -0,0 +1,13 @@
+<div class="flex flex-col">
+  <a href="{% firstof page.facebook page.root_page.facebook %}"
+     class="super-button bg-brands-facebook text-white container-padding--zero lg:container-padding--auto m-2">
+    <span class="super-button__body">Sledujte nás na Facebooku</span>
+    <i class="super-button__icon ico--facebook"></i>
+  </a>
+
+  <a href="{% firstof page.forum page.root_page.forum %}"
+     class="super-button bg-black text-white container-padding--zero lg:container-padding--auto m-2">
+    <span class="super-button__body">Sledujte naše fórum</span>
+    <i class="super-button__icon ico--bubbles"></i>
+  </a>
+</div>
-- 
GitLab