From 1c5ddf073baa039dbf09e5e6f3f577696c53dd07 Mon Sep 17 00:00:00 2001 From: Ondrej Rehounek <ondra.rehounek@seznam.cz> Date: Mon, 8 Nov 2021 21:51:21 +0100 Subject: [PATCH] district: unfortunately big commit containing: add some fields to existing pages, change and add some templates, prepare some stuff for region module --- district/blocks.py | 57 +++ .../migrations/0005_auto_20211108_2126.py | 120 ++++++ district/models.py | 165 +++++++-- district/templates/district/base.html | 34 +- .../blocks/homepage_header_block.html | 13 + .../district/blocks/program_block.html | 138 +++++++ .../district/district_article_page.html | 2 +- .../district/district_articles_page.html | 56 +-- .../district/district_contact_page.html | 81 +++-- .../district/district_home_page.html | 28 +- .../district/district_people_page.html | 19 +- .../district/district_person_page.html | 2 + .../district/district_program_page.html | 33 ++ .../district/district_tags_page.html | 39 +- .../templates/district/followus_snippet.html | 13 - .../district/social_icons_snippet.html | 5 - region/migrations/0001_initial.py | 140 +++++++ region/models.py | 341 +++++++++++++++++- region/templates/region/base.html | 286 +++++++++++++++ .../templates/region/region_article_page.html | 83 +++++ .../region/region_articles_page.html | 54 +++ .../templates/region/region_contact_page.html | 88 +++++ region/templates/region/region_home_page.html | 20 + .../templates/region/region_people_page.html | 22 ++ .../templates/region/region_person_page.html | 104 ++++++ .../templates/region/region_program_page.html | 33 ++ region/templates/region/region_tags_page.html | 26 ++ shared/templates/shared/article_preview.html | 5 +- shared/templates/shared/followus_snippet.html | 13 + .../shared}/more_articles_snippet.html | 0 .../shared/social_icons_snippet.html | 6 + .../styleguide/2.3.x/pagination.html | 8 +- 32 files changed, 1852 insertions(+), 182 deletions(-) create mode 100644 district/blocks.py create mode 100644 district/migrations/0005_auto_20211108_2126.py create mode 100644 district/templates/district/blocks/homepage_header_block.html create mode 100644 district/templates/district/blocks/program_block.html create mode 100644 district/templates/district/district_program_page.html delete mode 100644 district/templates/district/followus_snippet.html delete mode 100644 district/templates/district/social_icons_snippet.html create mode 100644 region/migrations/0001_initial.py create mode 100644 region/templates/region/base.html create mode 100644 region/templates/region/region_article_page.html create mode 100644 region/templates/region/region_articles_page.html create mode 100644 region/templates/region/region_contact_page.html create mode 100644 region/templates/region/region_home_page.html create mode 100644 region/templates/region/region_people_page.html create mode 100644 region/templates/region/region_person_page.html create mode 100644 region/templates/region/region_program_page.html create mode 100644 region/templates/region/region_tags_page.html create mode 100644 shared/templates/shared/followus_snippet.html rename {district/templates/district => shared/templates/shared}/more_articles_snippet.html (100%) create mode 100644 shared/templates/shared/social_icons_snippet.html diff --git a/district/blocks.py b/district/blocks.py new file mode 100644 index 00000000..950a9488 --- /dev/null +++ b/district/blocks.py @@ -0,0 +1,57 @@ +from django.forms import Select +from wagtail.contrib.table_block.blocks import TableBlock +from wagtail.core.blocks import ( + CharBlock, + ChooserBlock, + IntegerBlock, + ListBlock, + StructBlock, + TextBlock, + URLBlock, +) +from wagtail.images.blocks import ImageChooserBlock + +from shared.models import Person + + +class HomepageHeaderBlock(StructBlock): + title = CharBlock(label="Titulek", required=True) + subtitle = CharBlock(label="Podtitulek", required=False) + image = ImageChooserBlock() + + class Meta: + template = "district/blocks/homepage_header_block.html" + icon = "image" + label = "Nadpis s obrázkem" + + +class PersonChooserBlock(ChooserBlock): + target_model = Person + widget = Select + + # TODO check if this is needed + def value_for_form(self, value): + if isinstance(value, self.target_model): + return value.pk + else: + return value + + +class ProgramItemBlock(StructBlock): + title = CharBlock(label="Název", required=True) + issue_link = URLBlock(label="Odkaz na redmine", required=True) + completion_percentage = IntegerBlock(label="Procento dokončení", required=True) + + +class ProgramBlock(StructBlock): + headline = CharBlock(label="Titulek bloku", required=True) + perex = TextBlock(label="Krátký text pod nadpisem", required=True) + person = PersonChooserBlock(label="Osoba", required=True) + completion_percentage = IntegerBlock(label="Procento dokončení", required=True) + program_items = ListBlock(ProgramItemBlock()) + # program_items = TableBlock(label="Tabulka plnění programu", required=True) + + class Meta: + template = "district/blocks/program_block.html" + icon = "list-ul" + label = "Blok programu" diff --git a/district/migrations/0005_auto_20211108_2126.py b/district/migrations/0005_auto_20211108_2126.py new file mode 100644 index 00000000..8fca7300 --- /dev/null +++ b/district/migrations/0005_auto_20211108_2126.py @@ -0,0 +1,120 @@ +# Generated by Django 3.2.8 on 2021-11-08 20:26 + +import district.blocks +from django.db import migrations, models +import django.db.models.deletion +import modelcluster.contrib.taggit +import modelcluster.fields +import shared.models +import wagtail.core.blocks +import wagtail.core.fields +import wagtail.images.blocks +import wagtailmetadata.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailimages', '0023_add_choose_permissions'), + ('wagtailcore', '0062_comment_models_and_pagesubscription'), + ('shared', '0001_initial'), + ('taggit', '0003_taggeditem_add_unique_index'), + ('district', '0004_auto_20210209_1222'), + ] + + operations = [ + migrations.AlterModelOptions( + name='districthomepage', + options={'verbose_name': 'Web místního sdružení'}, + ), + migrations.RemoveField( + model_name='districthomepage', + name='content', + ), + migrations.AddField( + model_name='districtcontactpage', + name='text', + field=wagtail.core.fields.RichTextField(blank=True, verbose_name='Text'), + ), + migrations.AddField( + model_name='districthomepage', + name='articles_title', + field=models.CharField(default='Děje se', max_length=256, verbose_name='Nadpis článků'), + preserve_default=False, + ), + migrations.AddField( + model_name='districthomepage', + name='calendar_button_text', + field=models.CharField(default='Kalendář', max_length=256, verbose_name='Text tlačítka kalendáře'), + ), + migrations.AddField( + model_name='districthomepage', + name='calendar_embed_link', + field=models.URLField(default='', help_text="Mělo by začínat 'https://calendar.google.com/calendar/embed?...'", verbose_name='Odkaz na embed kalendář'), + preserve_default=False, + ), + migrations.AddField( + model_name='districthomepage', + name='region_map_button_text', + field=models.CharField(default='Piráti v krajích', max_length=256, verbose_name='Text tlačítka mapy'), + ), + migrations.AddField( + model_name='districthomepage', + name='subheader', + field=wagtail.core.fields.StreamField([('header', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(label='Titulek', required=True)), ('subtitle', wagtail.core.blocks.CharBlock(label='Podtitulek', required=False)), ('image', wagtail.images.blocks.ImageChooserBlock())]))], blank=True, verbose_name='Blok pod headerem'), + ), + migrations.AddField( + model_name='districthomepage', + name='twitter', + field=models.URLField(blank=True, null=True, verbose_name='Twitter URL'), + ), + migrations.AddField( + model_name='districthomepage', + name='youtube', + field=models.URLField(blank=True, null=True, verbose_name='YouTube URL'), + ), + migrations.AlterField( + model_name='districthomepage', + name='footperson_coord', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='district_footperson_coord', to='shared.person', verbose_name='Koordinátor'), + ), + migrations.AlterField( + model_name='districthomepage', + name='footperson_electman', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='district_footperson_electman', to='shared.person', verbose_name='Volební manažer'), + ), + migrations.AlterField( + model_name='districthomepage', + name='footperson_media', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='district_footperson_media', to='shared.person', verbose_name='Kontakt pro média'), + ), + migrations.CreateModel( + name='DistrictProgramPage', + 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')), + ('perex', models.TextField(blank=True, verbose_name='Perex')), + ('content', wagtail.core.fields.StreamField([('program_block', wagtail.core.blocks.StructBlock([('headline', wagtail.core.blocks.CharBlock(label='Titulek bloku', required=True)), ('perex', wagtail.core.blocks.TextBlock(label='Krátký text pod nadpisem', required=True)), ('person', district.blocks.PersonChooserBlock(label='Osoba', required=True)), ('completion_percentage', wagtail.core.blocks.IntegerBlock(label='Procento dokončení', required=True)), ('program_items', wagtail.core.blocks.ListBlock(wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.CharBlock(label='Název', required=True)), ('issue_link', wagtail.core.blocks.URLBlock(label='Odkaz na redmine', required=True)), ('completion_percentage', wagtail.core.blocks.IntegerBlock(label='Procento dokončení', required=True))])))]))], blank=True, verbose_name='obsah stránky')), + ('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': 'Program', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='DistrictPersonTag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content_object', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, to='district.districtpersonpage')), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='district_districtpersontag_items', to='taggit.tag')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='districtpersonpage', + name='groups', + field=modelcluster.contrib.taggit.ClusterTaggableManager(blank=True, help_text='Skupina pro zařazení na stránce Lidé', through='district.DistrictPersonTag', to='taggit.Tag', verbose_name='Tags'), + ), + ] diff --git a/district/models.py b/district/models.py index 4f33f986..0d1b76fc 100644 --- a/district/models.py +++ b/district/models.py @@ -5,7 +5,8 @@ from django.db import models from django.utils.translation import gettext_lazy from modelcluster.contrib.taggit import ClusterTaggableManager from modelcluster.fields import ParentalKey -from taggit.models import TaggedItemBase +from taggit.models import Tag, TaggedItemBase +from uniweb.constants import RICH_TEXT_FEATURES from wagtail.admin.edit_handlers import ( CommentPanel, FieldPanel, @@ -13,25 +14,39 @@ from wagtail.admin.edit_handlers import ( StreamFieldPanel, ) from wagtail.core import blocks -from wagtail.core.fields import StreamField +from wagtail.core.fields import RichTextField, StreamField from wagtail.core.models import Page from wagtailmetadata.models import MetadataPageMixin from shared.models import ArticleMixin, Person, SubpageMixin +from .blocks import HomepageHeaderBlock, ProgramBlock + class DistrictHomePage(MetadataPageMixin, Page): ### FIELDS - content = StreamField( - [ - ("title", blocks.CharBlock(label="nadpis", icon="title")), - ], - verbose_name="obsah stránky", + subheader = StreamField( + [("header", HomepageHeaderBlock())], + verbose_name="Blok pod headerem", blank=True, ) + articles_title = models.CharField("Nadpis článků", max_length=256) + region_map_button_text = models.CharField( + "Text tlačítka mapy", max_length=256, default="Piráti v krajích" + ) + calendar_button_text = models.CharField( + "Text tlačítka kalendáře", max_length=256, default="Kalendář" + ) + calendar_embed_link = models.URLField( + "Odkaz na embed kalendář", + help_text="Mělo by začínat 'https://calendar.google.com/calendar/embed?...'", + ) + facebook = models.URLField("Facebook URL", blank=True, null=True) + twitter = models.URLField("Twitter URL", blank=True, null=True) + youtube = models.URLField("YouTube URL", blank=True, null=True) forum = models.URLField("Fórum URL", blank=True, null=True) contact_email = models.EmailField("kontaktni email", max_length=250, blank=True) @@ -49,7 +64,7 @@ class DistrictHomePage(MetadataPageMixin, Page): on_delete=models.PROTECT, null=True, blank=True, - related_name="footperson_coord", + related_name="district_footperson_coord", ) footperson_electman = models.ForeignKey( Person, @@ -57,7 +72,7 @@ class DistrictHomePage(MetadataPageMixin, Page): on_delete=models.PROTECT, null=True, blank=True, - related_name="footperson_electman", + related_name="district_footperson_electman", ) footperson_media = models.ForeignKey( Person, @@ -65,7 +80,7 @@ class DistrictHomePage(MetadataPageMixin, Page): on_delete=models.PROTECT, null=True, blank=True, - related_name="footperson_media", + related_name="district_footperson_media", ) # settings @@ -76,7 +91,11 @@ class DistrictHomePage(MetadataPageMixin, Page): ### PANELS content_panels = Page.content_panels + [ - StreamFieldPanel("content"), + StreamFieldPanel("subheader"), + FieldPanel("articles_title"), + FieldPanel("region_map_button_text"), + FieldPanel("calendar_button_text"), + FieldPanel("calendar_embed_link"), ] promote_panels = [ @@ -84,6 +103,8 @@ class DistrictHomePage(MetadataPageMixin, Page): [ FieldPanel("facebook"), FieldPanel("forum"), + FieldPanel("twitter"), + FieldPanel("youtube"), ], gettext_lazy("Common page configuration"), ), @@ -117,13 +138,14 @@ class DistrictHomePage(MetadataPageMixin, Page): "district.DistrictArticlesPage", "district.DistrictContactPage", "district.DistrictPeoplePage", + "district.DistrictProgramPage", "district.DistrictTagsPage", ] ### OTHERS class Meta: - verbose_name = "Web místního sdružení (experimentální rozpracovaná verze!)" + verbose_name = "Web místního sdružení" def _first_subpage_of_type(self, page_type): return self.get_descendants().type(page_type).live().specific()[0] @@ -229,11 +251,13 @@ class DistrictContactPage(SubpageMixin, MetadataPageMixin, Page): verbose_name="Kontakty", blank=True, ) + text = RichTextField("Text", blank=True, features=RICH_TEXT_FEATURES) ### PANELS content_panels = Page.content_panels + [ StreamFieldPanel("contact_people"), + FieldPanel("text"), ] ### RELATIONS @@ -262,33 +286,86 @@ class DistrictTagsPage(SubpageMixin, MetadataPageMixin, Page): class Meta: verbose_name = "Stránka s tagy" - def get_context(self, request): + def get_context(self, request, *args, **kwargs) -> dict: context = super().get_context(request) - # Natrid clanky do hashtable dle tagu (v template by se to delalo podstatne hur) - tags = {} - for x in self.root_page.articles_page.get_children().live().specific(): - for y in x.tags.all(): - try: - tags[y.name].append(x) - except KeyError: - tags[y.name] = [x] + # Potřebujeme IDčka článků pro správnou root_page pro filtrování zobrazených + # tagů i samotných stránek, protože se filtrují přes specifický field + # (tags__slug) + site_article_ids = ( + self.root_page.articles_page.get_children() + .live() + .specific() + .values_list("id", flat=True) + ) + + # Naplním "tag" a "article_page_list" parametry + context.update(**self.get_tag_and_articles(request, site_article_ids)) + context["tag_list"] = self.get_tag_qs(site_article_ids) - context["tags"] = tags + # Pro obecnou paginaci posílám "extra_query", abych si podržel tag pro další GET + context["extra_query"] = "&tag={}".format(request.GET.get("tag", "")) return context + def get_tag_and_articles(self, request, site_article_ids: list) -> dict: + """ + Vrátí vyfiltrované články podle tagu a page query pro z daného "výběru" + pro danou stránku (site_article_ids). Lepší by bylo články a tag řešit + separátně, ale pak by se musel rozpadnout ten try/except na více bloků. + """ + article_page_qs = DistrictArticlePage.objects.filter(id__in=site_article_ids) + + try: + tag = DistrictArticleTag.objects.filter(tag__slug=request.GET["tag"])[0].tag + article_page_qs = article_page_qs.filter(tags__slug=tag.slug) + except (KeyError, IndexError): + tag = None + + return { + "article_page_list": Paginator( + article_page_qs, + self.root_page.articles_page.max_items, + ).get_page(request.GET.get("page")), + "tag": tag, + } + + @staticmethod + def get_tag_qs(site_article_ids: list) -> models.QuerySet: + """ + Getuje Tagy pouze pro DistrictArticlePage omezeno IDčky getnutých přes + root_page. Počítá, kolik článků je s daným tagem. + """ + return ( + Tag.objects.filter(districtarticlepage__id__in=site_article_ids) + .order_by("slug") + .annotate(count=models.Count("slug")) + .values("name", "slug", "count") + ) + + +class DistrictPersonTag(TaggedItemBase): + content_object = ParentalKey( + "district.DistrictPersonPage", on_delete=models.CASCADE + ) + class DistrictPersonPage(SubpageMixin, MetadataPageMixin, Page): ### FIELDS - person = models.ForeignKey(Person, on_delete=models.PROTECT, null=True) + groups = ClusterTaggableManager( + through=DistrictPersonTag, + blank=True, + help_text="Skupina pro zařazení na stránce Lidé", + ) perex = models.TextField("Perex osoby", blank=True) + person = models.ForeignKey(Person, on_delete=models.PROTECT, null=True) ### PANELS content_panels = Page.content_panels + [ FieldPanel("person"), FieldPanel("perex"), + FieldPanel("groups"), ] ### RELATIONS @@ -303,8 +380,9 @@ class DistrictPersonPage(SubpageMixin, MetadataPageMixin, Page): @property def pageperex(self): - """Vraci perex Pirata nejblizzsi lokalnimu kontextu. - Zamerne jiny nazev, aby v template bylo na vyber z x.perex, x.person.perex a x.pageperex + """ + Vraci perex Pirata nejblizzsi lokalnimu kontextu. Zamerne jiny nazev, aby + v template bylo na vyber z x.perex, x.person.perex a x.pageperex """ return self.perex or self.person.perex @@ -334,5 +412,40 @@ class DistrictPeoplePage(SubpageMixin, MetadataPageMixin, Page): def get_context(self, request): context = super().get_context(request) - context["people"] = self.get_children().live().specific() + + # Groupy (tagy) si natáhnu přes QS s orderingem, abych mohl udělat regroup v šabloně + context["district_person_tag_qs"] = DistrictPersonTag.objects.select_related( + "content_object" + ).order_by("tag_id") + return context + + +class DistrictProgramPage(SubpageMixin, MetadataPageMixin, Page): + ### FIELDS + + perex = models.TextField("Perex", blank=True) + content = StreamField( + [ + ("program_block", ProgramBlock()), + ], + verbose_name="obsah stránky", + blank=True, + ) + + ### PANELS + + content_panels = Page.content_panels + [ + FieldPanel("perex"), + StreamFieldPanel("content"), + ] + + ### RELATIONS + + parent_page_types = ["district.DistrictHomePage"] + subpage_types = [] + + ### OTHERS + + class Meta: + verbose_name = "Program" diff --git a/district/templates/district/base.html b/district/templates/district/base.html index 8434d04d..4653aa6d 100644 --- a/district/templates/district/base.html +++ b/district/templates/district/base.html @@ -72,7 +72,7 @@ </div> <div class="social-icon-group space-x-2 text-grey-200 py-4 lg:py-0"> - {% include "district/social_icons_snippet.html" %} + {% include "shared/social_icons_snippet.html" %} </div> </div> @@ -119,22 +119,29 @@ <nav class="subnav py-2"> <div class="container container--wide"> <div class="flex"> - - {% comment %} - <button @click="toggleView('regions')" class="btn btn--condensed btn--grey-500 btn--hoveractive btn--to-white text-sm mr-2 px-0" :class="{'btn--activated': isCurrentView('regions')}"> + <button + class="btn btn--condensed btn--grey-500 btn--hoveractive btn--to-white text-sm mr-2 px-0" + :class="{'btn--activated': isCurrentView('regions')}" + @click="toggleView('regions')" + > <div class="btn__body py-2"> - <span>Piráti v dalších krajích</span> + <span>{{ page.root_page.region_map_button_text }}</span> <i class="ico--chevron-down ml-4"></i> </div> </button> - <button @click="toggleView('calendar')" class="btn btn--inline-icon btn--condensed btn--hoveractive btn--grey-500 btn--to-orange-300 text-sm px-0" :class="{'btn--activated': isCurrentView('calendar')}"> + <button + class="btn btn--inline-icon btn--condensed btn--hoveractive btn--grey-500 btn--to-orange-300 text-sm px-0" + :class="{'btn--activated': isCurrentView('calendar')}" + @click="toggleView('calendar')" + > <div class="btn__body py-2"> <i class="btn__inline-icon ico--calendar mr-0 md:mr-2 text-orange-300"></i> - <span class="hidden md:block">Krajský kalendář</span> + <span class="hidden md:block"> + {{ page.root_page.calendar_button_text|default_if_none:"Kalendář" }} + </span> </div> </button> - {% endcomment %} {% if page.root_page.facebook %} <a href="{{ page.root_page.facebook }}" target="_blank" rel="noopener noreferrer" class="btn btn--inline-icon btn--condensed btn--hoveractive btn--grey-500 btn--to-brands-facebook text-sm ml-2 px-0"> @@ -151,16 +158,15 @@ <aside class="subnav-aside"> <div class="subnav-aside__item" :class="{'subnav-aside__item--visible': isCurrentView('regions')}"> - <a @click="toggleView('regions')" class="subnav-aside__close"><i class="ico--close"></i></a> +{# <a @click="toggleView('regions')" class="subnav-aside__close"><i class="ico--close"></i></a>#} <ui-region-map class="container container--default" /> </div> <div class="subnav-aside__item" :class="{'subnav-aside__item--visible': isCurrentView('calendar')}"> - <a @click="toggleView('calendar')" class="subnav-aside__close"><i class="ico--close"></i></a> +{# <a @click="toggleView('calendar')" class="subnav-aside__close"><i class="ico--close"></i></a>#} <div class="container container--default"> - - <iframe src="https://calendar.google.com/calendar/embed?showTitle=0&showNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&showTz=0&mode=AGENDA&height=500&wkst=2&hl=cs&bgcolor=%23FFFFFF&src=kddvdvu3adcjef2kro4j6mm838%40group.calendar.google.com&color=%232952A3&ctz=Europe%2FPrague" style="border-width:0; width: 100%; height: 410px; border: 0; overflow: hidden;"></iframe> + <iframe src="{{ page.root_page.calendar_embed_link }}" style="border-width:0; width: 100%; height: 410px; border: 0; overflow: hidden;"></iframe> <p class="mt-4"> - <a class="btn btn--orange-200 btn--hoveractive" href="https://calendar.google.com/calendar/embed?showTitle=0&showNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&showTz=0&mode=AGENDA&height=500&wkst=2&hl=cs&bgcolor=%23FFFFFF&src=kddvdvu3adcjef2kro4j6mm838%40group.calendar.google.com&color=%232952A3&ctz=Europe%2FPrague"> + <a class="btn btn--orange-200 btn--hoveractive" href="{{ page.root_page.calendar_embed_link }}"> <span class="btn__body">Zobrazit všechny akce</span> </a> </p> @@ -230,7 +236,7 @@ <section class="footer__social lg:text-right"> <div class="mb-4"> <div class="social-icon-group space-x-2 text-white pb-4"> - {% include "district/social_icons_snippet.html" %} + {% include "shared/social_icons_snippet.html" %} </div> <a href="mailto:{{ page.root_page.contact_email|default:"info@pirati.cz" }}" class="contact-line icon-link content-block--nostyle " ><i class="ico--envelope"></i><span>Dejte nám vědět</span></a> </div> diff --git a/district/templates/district/blocks/homepage_header_block.html b/district/templates/district/blocks/homepage_header_block.html new file mode 100644 index 00000000..bf9c6076 --- /dev/null +++ b/district/templates/district/blocks/homepage_header_block.html @@ -0,0 +1,13 @@ +<header + class="hero hero--image py-16 " + style="--image-url: url(https://praha8.pirati.cz/assets/posts/libensky-zamek-c76ce3fd0a7d061e15025fbb7080f4dbd12fab3daebdcbd42d2ab6b1cdbaa2f0.jpg)" +> + <div class="container container--default"> + <h1 class="head-alt-md md:head-alt-lg max-w-2xl "> + Piráti Praha 8 + </h1> + <h2 class="head-xs mt-2 "> + Makáme v opozici. Držíme směr! + </h2> + </div> +</header> diff --git a/district/templates/district/blocks/program_block.html b/district/templates/district/blocks/program_block.html new file mode 100644 index 00000000..c4f9ee1e --- /dev/null +++ b/district/templates/district/blocks/program_block.html @@ -0,0 +1,138 @@ +<article class="mt-8"> + <div class="lg:flex lg:space-x-16"> + <div class="lg:w-3/5 xl:w-2/3"> + <h2 class="head-heavy-sm mb-2 lg:mb-4"> + {{ self.headline }} + </h2> + <div itemprop="description" class="w-full content-block"> + <p> + {{ self.perex }} + </p> + </div> + </div> + <div class="pt-8 lg:w-1/3 md:pt-0"> + <div class="card"> + <div class="card__body"> + <div class="badge badge--condensed"> + <a href="/lide/martin-stanek.html" class="avatar badge__avatar avatar--sm"> + <img src="/assets/bac4c3-0c8ce9ef9b8e4b48c898da14ee6fba5b78836ed019538622f72b4c6584aee7b6.jpg" + alt="Martin Staněk"> + </a> + <div class="badge__body"> + <h2 class="head-heavy-2xs badge__title"> + <a href="/lide/martin-stanek.html" title="Martin Staněk" class="content-block--nostyle"> + Martin Staněk + </a> + </h2> + <p class="badge__occupation"> + Garant + </p> + + <a href="tel:775 058 555" + class="contact-line icon-link content-block--nostyle contact-line--responsive badge__link"> + <i class="ico--phone"></i> + <span>775 058 555</span> + </a> + + <a href="mailto:martin.stanek@pirati.cz" + class="contact-line icon-link content-block--nostyle contact-line--responsive badge__link"> + <i class="ico--envelope"></i> + <span>martin.stanek@pirati.cz</span> + </a> + </div> + </div> + + <div class="content-block"> + <div class="space-y-4 mt-8"> + <div> + <a href="https://redmine.pirati.cz/issues/28177" class="contact-line icon-link content-block--nostyle"> + <i class="ico--info"></i> + <span id="redmineid_28177">Plnění programu: 10%</span> + </a> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + + <div class="mt-4"> + <table class="table table--striped table--bordered w-full"> + <thead> + <tr> + <td>Název</td> + <td>Stav plnění</td> + </tr> + </thead> + <tbody> + {% for item in self.program_items %} + <tr> + <td> + <a href="{{ item.issue_link }}" target="_blank"> + {{ item.title }} + </a> + </td> + <td>{{ item.completion_percentage }} %</td> + </tr> + {% endfor %} + </tbody> + </table> + </div> +</article> + +<div class="content-block"> + <div class="space-y-4 mt-8"> + <div> + <a href="https://redmine.pirati.cz/issues/28177" class="contact-line icon-link content-block--nostyle"> + <i class="ico--info"></i> + <span id="redmineid_28177">Plnění programu: 10%</span> + </a> + </div> + </div> +</div> + +<script> + fetch('https://redmine.pirati.cz/issues/28177.json') + .then(response => response.json()) + .then(data => console.log(data)); + + fetch('https://redmine.pirati.cz/issues.json?parent_id=28177&sort=id:as') + .then(response => response.json()) + .then(data => console.log(data)); + + {#pirates.priorityStack.push(function (context) {#} + {# var url = 'https://redmine.pirati.cz/issues/28177.json';#} + {# var xhr = pirates.createCORSRequest('GET', url);#} + {# if (!xhr) {#} + {# alert('CORS not supported');#} + {# return;#} + {# }#} + {# xhr.onload = function () {#} + {# var doc = JSON.parse(xhr.responseText);#} + {# var redmine = document.getElementById('redmineid_28177');#} + {# redmine.textContent = "Plnění programu: " + doc.issue.done_ratio + "%";#} + {# }#} + {# xhr.onerror = function () {#} + {# console.log('Woops, there was an error making the request.');#} + {# };#} + {# xhr.send();#} + {#});#} + {#pirates.priorityStack.push(function (context) {#} + {# var url = 'https://redmine.pirati.cz/issues.json?parent_id=28177&sort=id:asc';#} + {# var xhr = pirates.createCORSRequest('GET', url);#} + {# if (!xhr) {#} + {# alert('CORS not supported');#} + {# return;#} + {# }#} + {# xhr.onload = function () {#} + {# var doc = JSON.parse(xhr.responseText);#} + {# var div = document.getElementById('redmine_tasks_28177');#} + {# div.appendChild(pirates.integrations.redmine.tasks(doc));#} + {# }#} + {# xhr.onerror = function () {#} + {# console.log('Woops, there was an error making the request.');#} + {# };#} + {# xhr.send();#} + {#});#} +</script> diff --git a/district/templates/district/district_article_page.html b/district/templates/district/district_article_page.html index a02c4056..e618a634 100644 --- a/district/templates/district/district_article_page.html +++ b/district/templates/district/district_article_page.html @@ -77,7 +77,7 @@ </div> -{% include "district/more_articles_snippet.html" %} +{% include "shared/more_articles_snippet.html" %} {% endblock %} diff --git a/district/templates/district/district_articles_page.html b/district/templates/district/district_articles_page.html index 1d89ee4c..69c472dc 100644 --- a/district/templates/district/district_articles_page.html +++ b/district/templates/district/district_articles_page.html @@ -1,54 +1,22 @@ {% extends "district/base.html" %} {% block content %} -<main> + <main> - <div class="container container--default py-8 lg:py-24"> + <div class="container container--default py-8 lg:py-24"> - <header> - <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> - </header> + <header> + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> + </header> - <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8"> - {% for a in articles %} - {% include "shared/article_preview.html" with article=a %} - {% endfor %} - </div> - - <div class="pagination-container" role="navigation" aria-label="Pagination"> - <nav> - - {% if articles.has_previous %} - <a href="{{ page.root_page.articles_page.url }}?page={{ articles.previous_page_number }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed btn--inverted-icon px-0" aria-label="Předchozí stránka"> - <div class="btn__body-wrap"> - <div class="btn__body ">Předchozí</div> - <div class="btn__icon "> - <i class="ico--chevron-left"></i> - </div> - </div> - </a> - {% endif %} - - {% for i in articles.paginator.page_range %} - <a href="{{ page.root_page.articles_page.url }}?page={{ i }}" class="btn {% if i == articles.number %} btn--grey-500 {% else %} btn--grey-125 {% endif %} btn--hoveractive btn--to-black btn--condensed hidden md:inline-block px-0" aria-label="Stránka {{ i }}"> - <div class="btn__body ">{{ i }}</div> - </a> - {% endfor %} - - {% if articles.has_next %} - <a href="{{ page.root_page.articles_page.url }}?page={{ articles.next_page_number }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed px-0" aria-label="Další stránka"> - <div class="btn__body-wrap"> - <div class="btn__body ">Další</div> - <div class="btn__icon "> - <i class="ico--chevron-right"></i> - </div> - </div> - </a> - {% endif %} + <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8"> + {% for a in articles %} + {% include "shared/article_preview.html" with article=a %} + {% endfor %} + </div> - </nav> + {% include 'styleguide/2.3.x/pagination.html' with paginator=article_page_list %} </div> - </div> -</main> + </main> {% endblock %} diff --git a/district/templates/district/district_contact_page.html b/district/templates/district/district_contact_page.html index a5bd3d0b..b1c6c77b 100644 --- a/district/templates/district/district_contact_page.html +++ b/district/templates/district/district_contact_page.html @@ -3,66 +3,68 @@ {% block content %} -<div class="container container--default py-8"> - - + <div class="container container--default py-8"> <div class="lg:flex lg:mt-8 space-y-16 lg:space-y-0 lg:space-x-8 xl:space-x-16 mb-5"> <section class="lg:w-3/5 xl:w-2/3"> - <header> - <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> - </header> + <header> + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> + </header> - {% for item in page.contact_people %} + {% for item in page.contact_people %} - <div> - <h2 class="head-heavy-sm mb-2 lg:mb-4 mt-4">{{ item.value.name }}</h2> - <div class="card elevation-3 p-3 mb-3"> - {% include "shared/person_badge_snippet.html" with person=item.value.person %} - </div> - </div> + <div> + <h2 class="head-heavy-sm mb-2 lg:mb-4 mt-4">{{ item.value.name }}</h2> + <div class="card elevation-3 p-3 mb-3"> + {% include "shared/person_badge_snippet.html" with person=item.value.person %} + </div> + </div> + + {% endfor %} - {% endfor %} + <div class="content-block"> + {{ page.text | richtext }} + </div> - </section> + </section> - <section class="lg:w-2/5 xl:w-1/3 lg:pt-0"> - <div class="lg:card lg:elevation-10"> - <div class="lg:card__body content-block"> + <section class="lg:w-2/5 xl:w-1/3 lg:pt-0"> + <div class="lg:card lg:elevation-10"> + <div class="lg:card__body content-block"> <h2>Základní údaje</h2> <div class="space-y-4"> <div> - <h4>Emailová adresa</h4> - <a href="mailto:yveta.martinkova@pirati.cz" class="contact-line icon-link content-block--nostyle " > - <i class="ico--envelope"></i><span>{{ page.root_page.contact_email }}</span> - </a> + <h4>Emailová adresa</h4> + <a href="mailto:yveta.martinkova@pirati.cz" class="contact-line icon-link content-block--nostyle "> + <i class="ico--envelope"></i><span>{{ page.root_page.contact_email }}</span> + </a> </div> <div> - <h4>Telefonický kontakt</h4> - <a href="tel:{{ page.root_page.contact_phone }}" class="contact-line icon-link content-block--nostyle " > - <i class="ico--phone"></i><span>{{ page.root_page.contact_phone }}</span> - </a> + <h4>Telefonický kontakt</h4> + <a href="tel:{{ page.root_page.contact_phone }}" class="contact-line icon-link content-block--nostyle "> + <i class="ico--phone"></i><span>{{ page.root_page.contact_phone }}</span> + </a> </div> <div> - <h4>Transparentní účty</h4> - 2100048174/2010 a <a href="https://wiki.pirati.cz/fo/seznam_uctu">další účty</a> + <h4>Transparentní účty</h4> + 2100048174/2010 a <a href="https://wiki.pirati.cz/fo/seznam_uctu">další účty</a> </div> <div> - <h4>Datová schránka</h4> - <span class="contact-line icon-link content-block--nostyle " > + <h4>Datová schránka</h4> + <span class="contact-line icon-link content-block--nostyle "> <i class="ico--drawer"></i><span>b2i4r6j</span></span> </div> <div> - <h4>Celostátní web</h4> - <a href="https://www.pirati.cz" class="contact-line icon-link content-block--nostyle " > - <i class="ico--pirati"></i><span>www.pirati.cz</span> - </a> + <h4>Celostátní web</h4> + <a href="https://www.pirati.cz" class="contact-line icon-link content-block--nostyle "> + <i class="ico--pirati"></i><span>www.pirati.cz</span> + </a> </div> <p>Každý člen strany má email ve tvaru: <tt>jmeno.prijmeni@pirati.cz</tt></p> @@ -74,14 +76,13 @@ <h2>Sídlo a kontaktní centrum</h2> <strong>Piráti Zlínský kraj</strong> + </div> </div> - </div> - </section> - - </div> + </section> + </div> - {% include "district/followus_snippet.html" %} + {% include "shared/followus_snippet.html" %} -</div> + </div> {% endblock %} diff --git a/district/templates/district/district_home_page.html b/district/templates/district/district_home_page.html index 275f6237..1915413c 100644 --- a/district/templates/district/district_home_page.html +++ b/district/templates/district/district_home_page.html @@ -1,20 +1,28 @@ {% extends "district/base.html" %} {% load wagtailcore_tags %} -{% block content %} -<main> - - <h1 class="head-alt-md md:head-alt-lg pb-4 lg:pb-8 pt-5">Aktuální témata</h1> +{% block subheader %} + {% for block in page.subheader %} + {% include_block block %} + {% endfor %} +{% endblock subheader %} +{% block content %} + <main> + <h2 class="head-alt-md pb-4 lg:pb-8"> + {{ page.articles_title }} + </h2> <!-- list of articles --> <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8"> - {% for a in page.articles %} - {% include "shared/article_preview.html" with article=a %} - {% endfor %} + {% for a in page.articles %} + {% include "shared/article_preview.html" with article=a %} + {% endfor %} </div> - {% include "district/more_articles_snippet.html" %} - {% include "district/followus_snippet.html" %} + <div class="mb-8"> + {% include "shared/more_articles_snippet.html" %} + </div> -</main> + {% include "shared/followus_snippet.html" %} + </main> {% endblock %} diff --git a/district/templates/district/district_people_page.html b/district/templates/district/district_people_page.html index a0228fde..2debc43a 100644 --- a/district/templates/district/district_people_page.html +++ b/district/templates/district/district_people_page.html @@ -9,14 +9,21 @@ <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> </header> - <h2 class="head-heavy-base mb-4">Členové a příznivci</h2> + {% regroup district_person_tag_qs by tag as person_group_list %} - <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 row-gap-8 col-gap-8"> - {% for person in people %} - {% include "shared/person_badge_snippet.html" with person=person %} + {% for person_group in person_group_list %} + <h2 class="head-heavy-base mb-4"> + {{ person_group.grouper.name }} + </h2> + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 row-gap-8 col-gap-8"> + {% for group_tag in person_group.list %} + {% include "shared/person_badge_snippet.html" with person=group_tag.content_object %} + {% endfor %} + </div> + {% if not forloop.last %} + <hr class="hr--big"> + {% endif %} {% endfor %} - </div> - </div> {% endblock %} diff --git a/district/templates/district/district_person_page.html b/district/templates/district/district_person_page.html index fa889e7f..2ff22ccd 100644 --- a/district/templates/district/district_person_page.html +++ b/district/templates/district/district_person_page.html @@ -48,6 +48,8 @@ </div> {% endif %} + {{ page.person.name }} + <div class="content-block"> <hr /> <div class="space-y-4"> diff --git a/district/templates/district/district_program_page.html b/district/templates/district/district_program_page.html new file mode 100644 index 00000000..8637887c --- /dev/null +++ b/district/templates/district/district_program_page.html @@ -0,0 +1,33 @@ +{% extends "district/base.html" %} +{% load wagtailcore_tags wagtailimages_tags shared_filters %} + +{% block content %} + + <div class="container container--default py-8"> + <div class="lg:flex lg:mt-8 space-y-16 lg:space-y-0 lg:space-x-8 xl:space-x-16 mb-5"> + <section> + + <header> + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8"> + {{ page.title }} + </h1> + </header> + + <p> + {{ page.perex }} + </p> + +{# {{ page.content }}#} + + {% for block in page.content %} + + {% include_block block %} + + {% endfor %} + + </section> + + </div> + </div> + +{% endblock %} diff --git a/district/templates/district/district_tags_page.html b/district/templates/district/district_tags_page.html index e4feb3fe..30f7ebd0 100644 --- a/district/templates/district/district_tags_page.html +++ b/district/templates/district/district_tags_page.html @@ -1,26 +1,31 @@ {% extends "district/base.html" %} {% block content %} -<main> + <main> - <h1 class="head-alt-md md:head-alt-lg max-w-5xl mb-4 mt-5">{{ page }}</h1> + <h1 class="head-alt-md md:head-alt-lg max-w-5xl mb-4 mt-5"> + {% if tag %}{{ page.title }} "{{ tag.name }}"{% else %}Výběr z článků{% endif %} + </h1> - <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> - {% for tag, articles in tags.items %} + <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8"> + {% for a in article_page_list %} + {% include "shared/article_preview.html" with article=a %} + {% endfor %} + </div> - <section class="card"> - <div class="card__body p-4"> - <h3 class="head-heavy-xs mb-2" id="{{ tag }}">{{ tag }}</h3> - <ul class="unordered-list unordered-list--linked unordered-list--dense leading-normal font-light text-sm"> - {% for x in articles %} - <li><a href="{{ x.url }}">{{ x }}</a></li> - {% endfor %} - </ul> - </div> - </section> + {% include 'styleguide/2.3.x/pagination.html' with paginator=article_page_list %} - {% endfor %} - </div> + <h2 class="mt-8 head-alt-base">Další štítky:</h2> -</main> + <div class="inline-block-nogap mt-4"> + {% for tag in tag_list %} + <a + href="{{ page.url }}?tag={{ tag.slug }}" + class="btn article-card__category-button btn--condensed text-sm font-light btn--grey-{% if tag.slug == request.GET.tag %}500{% else %}125{% endif %} btn--hoveractive" + > + <div class="btn__body ">{{ tag.name }} ({{ tag.count }})</div> + </a> + {% endfor %} + </div> + </main> {% endblock %} diff --git a/district/templates/district/followus_snippet.html b/district/templates/district/followus_snippet.html deleted file mode 100644 index c6c7ca96..00000000 --- a/district/templates/district/followus_snippet.html +++ /dev/null @@ -1,13 +0,0 @@ - <div class="d-flex"> - - <a href="{{page.facebook}}" class="super-button bg-brands-facebook text-white container-padding--zero lg:container-padding--auto lg:w-full 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 }}" class="super-button bg-black text-white container-padding--zero lg:container-padding--auto lg:w-full m-2" > - <span class="super-button__body">Sledujte naše fórum</span> - <i class="super-button__icon ico--bubbles"></i> - </a> - - </div> diff --git a/district/templates/district/social_icons_snippet.html b/district/templates/district/social_icons_snippet.html deleted file mode 100644 index 89a60835..00000000 --- a/district/templates/district/social_icons_snippet.html +++ /dev/null @@ -1,5 +0,0 @@ -<a href="https://www.twitter.com/PiratskaStrana" rel="noopener noreferrer" target="_blank" title="Náš účet na Twitteru" class="social-icon "><i class="ico--twitter"></i></a> -<a href="/feed.xml" rel="noopener noreferrer" target="_blank" title="Články tohoto webu v RSS" class="social-icon "><i class="ico--feed"></i></a> -<a href=https://www.instagram.com/pirati.cz/ rel="noopener noreferrer" target="_blank" title="Instagram - Česká pirátská strana" class="social-icon "><i class="ico--instagram"></i></a> -<a href=https://www.flickr.com/photos/pirati/ rel="noopener noreferrer" target="_blank" title="Flickr - Česká pirátská strana" class="social-icon "><i class="ico--flickr"></i></a> -<a href="mailto:{{ page.root_page.contact_email|default:"info@pirati.cz" }}" class="social-icon "><i class="ico--envelope"></i></a> diff --git a/region/migrations/0001_initial.py b/region/migrations/0001_initial.py new file mode 100644 index 00000000..5e59b9d1 --- /dev/null +++ b/region/migrations/0001_initial.py @@ -0,0 +1,140 @@ +# Generated by Django 3.2.8 on 2021-11-08 20:43 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import modelcluster.contrib.taggit +import modelcluster.fields +import shared.models +import wagtail.core.blocks +import wagtail.core.fields +import wagtailmetadata.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0062_comment_models_and_pagesubscription'), + ('wagtailimages', '0023_add_choose_permissions'), + ('shared', '0001_initial'), + ('taggit', '0003_taggeditem_add_unique_index'), + ] + + operations = [ + migrations.CreateModel( + name='RegionArticlePage', + 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')), + ('date', models.DateField(default=django.utils.timezone.now, verbose_name='datum')), + ('perex', models.TextField(verbose_name='perex')), + ('text', wagtail.core.fields.RichTextField(blank=True, verbose_name='článek')), + ('author', models.CharField(blank=True, max_length=250, null=True, verbose_name='autor')), + ('image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='wagtailimages.image', verbose_name='obrázek')), + ('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': 'Aktualita', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='RegionTagsPage', + 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')), + ('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 s tagy', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='RegionPersonPage', + 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')), + ('perex', models.TextField(blank=True, verbose_name='Perex osoby')), + ('person', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='shared.person')), + ('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': 'Detail osoby', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='RegionPeoplePage', + 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')), + ('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': 'Lidé', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='RegionHomePage', + 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')), + ('content', wagtail.core.fields.StreamField([('title', wagtail.core.blocks.CharBlock(icon='title', label='nadpis'))], blank=True, verbose_name='obsah stránky')), + ('facebook', models.URLField(blank=True, null=True, verbose_name='Facebook URL')), + ('forum', models.URLField(blank=True, null=True, verbose_name='Fórum URL')), + ('contact_email', models.EmailField(blank=True, max_length=250, verbose_name='kontaktni email')), + ('contact_phone', models.TextField(blank=True, max_length=250, verbose_name='kontaktni telefon')), + ('contact_newcomers', models.URLField(blank=True, null=True, verbose_name='URL pro zájemce o členství')), + ('donation_page', models.URLField(blank=True, null=True, verbose_name='URL pro příjem darů')), + ('matomo_id', models.IntegerField(blank=True, null=True, verbose_name='Matomo ID pro sledování návštěvnosti')), + ('footperson_coord', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='region_footperson_coord', to='shared.person', verbose_name='Koordinátor')), + ('footperson_electman', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='region_footperson_electman', to='shared.person', verbose_name='Volební manažer')), + ('footperson_media', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='region_footperson_media', to='shared.person', verbose_name='Kontakt pro média')), + ('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': 'Web regionálního sdružení', + }, + bases=(wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='RegionContactPage', + 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')), + ('contact_people', wagtail.core.fields.StreamField([('item', wagtail.core.blocks.StructBlock([('name', wagtail.core.blocks.CharBlock(label='Role')), ('person', wagtail.core.blocks.PageChooserBlock(label='Osoba', page_type=['region.RegionPersonPage']))]))], blank=True, verbose_name='Kontakty')), + ('text', wagtail.core.fields.RichTextField(blank=True, verbose_name='Text')), + ('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': 'Kontakty', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='RegionArticleTag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content_object', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, to='region.regionarticlepage')), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='region_regionarticletag_items', to='taggit.tag')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='RegionArticlesPage', + 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')), + ('max_items', models.IntegerField(default=12, verbose_name='Počet článků na stránce')), + ('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': 'Aktuality', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.AddField( + model_name='regionarticlepage', + name='tags', + field=modelcluster.contrib.taggit.ClusterTaggableManager(blank=True, help_text='A comma-separated list of tags.', through='region.RegionArticleTag', to='taggit.Tag', verbose_name='Tags'), + ), + ] diff --git a/region/models.py b/region/models.py index 71a83623..81ed0d9f 100644 --- a/region/models.py +++ b/region/models.py @@ -1,3 +1,342 @@ +import random + +from django.core.paginator import Paginator from django.db import models +from django.utils.translation import gettext_lazy +from modelcluster.contrib.taggit import ClusterTaggableManager +from modelcluster.fields import ParentalKey +from taggit.models import TaggedItemBase +from uniweb.constants import RICH_TEXT_FEATURES +from wagtail.admin.edit_handlers import ( + CommentPanel, + FieldPanel, + MultiFieldPanel, + StreamFieldPanel, +) +from wagtail.core import blocks +from wagtail.core.fields import RichTextField, StreamField +from wagtail.core.models import Page +from wagtailmetadata.models import MetadataPageMixin + +from shared.models import ArticleMixin, Person, SubpageMixin + + +# TODO zatím prakticky shodné s district.models - až bude hotové, tak společné věci přenést do shared + + +class RegionHomePage(MetadataPageMixin, Page): + ### FIELDS + + content = StreamField( + [ + ("title", blocks.CharBlock(label="nadpis", icon="title")), + ], + verbose_name="obsah stránky", + blank=True, + ) + + facebook = models.URLField("Facebook URL", blank=True, null=True) + forum = models.URLField("Fórum URL", blank=True, null=True) + + contact_email = models.EmailField("kontaktni email", max_length=250, blank=True) + contact_phone = models.TextField("kontaktni telefon", max_length=250, blank=True) + contact_newcomers = models.URLField( + "URL pro zájemce o členství", blank=True, null=True + ) + + donation_page = models.URLField("URL pro příjem darů", blank=True, null=True) + + # Lide uvedeni v paticce + footperson_coord = models.ForeignKey( + Person, + verbose_name="Koordinátor", + on_delete=models.PROTECT, + null=True, + blank=True, + related_name="region_footperson_coord", + ) + footperson_electman = models.ForeignKey( + Person, + verbose_name="Volební manažer", + on_delete=models.PROTECT, + null=True, + blank=True, + related_name="region_footperson_electman", + ) + footperson_media = models.ForeignKey( + Person, + verbose_name="Kontakt pro média", + on_delete=models.PROTECT, + null=True, + blank=True, + related_name="region_footperson_media", + ) + + # settings + matomo_id = models.IntegerField( + "Matomo ID pro sledování návštěvnosti", blank=True, null=True + ) + + ### PANELS + + content_panels = Page.content_panels + [ + StreamFieldPanel("content"), + ] + + promote_panels = [ + MultiFieldPanel( + [ + FieldPanel("facebook"), + FieldPanel("forum"), + ], + gettext_lazy("Common page configuration"), + ), + ] + + settings_panels = [ + FieldPanel("matomo_id"), + FieldPanel("donation_page"), + MultiFieldPanel( + [ + FieldPanel("contact_email"), + FieldPanel("contact_phone"), + FieldPanel("contact_newcomers"), + ], + gettext_lazy("Kontakty"), + ), + MultiFieldPanel( + [ + FieldPanel("footperson_coord"), + FieldPanel("footperson_electman"), + FieldPanel("footperson_media"), + ], + gettext_lazy("Lidé v zápatí stránky"), + ), + CommentPanel(), + ] + + ### RELATIONS + + subpage_types = [ + "region.RegionArticlesPage", + "region.RegionContactPage", + "region.RegionPeoplePage", + "region.RegionTagsPage", + ] + + ### OTHERS + + class Meta: + verbose_name = "Web regionálního sdružení" + + def _first_subpage_of_type(self, page_type): + return self.get_descendants().type(page_type).live().specific()[0] + + @property + def articles(self): + return self.get_descendants().type(RegionArticlePage).live().specific() + + @property + def articles_page(self): + return self._first_subpage_of_type(RegionArticlesPage) + + @property + def people_page(self): + return self._first_subpage_of_type(RegionPeoplePage) + + @property + def contact_page(self): + return self._first_subpage_of_type(RegionContactPage) + + @property + def tags_page(self): + return self._first_subpage_of_type(RegionTagsPage) + + @property + def root_page(self): + return self + + +class RegionArticleTag(TaggedItemBase): + content_object = ParentalKey("region.RegionArticlePage", on_delete=models.CASCADE) + + +class RegionArticlePage(ArticleMixin, SubpageMixin, MetadataPageMixin, Page): + ### FIELDS + + tags = ClusterTaggableManager(through=RegionArticleTag, blank=True) + + ### PANELS + + content_panels = ArticleMixin.content_panels + [FieldPanel("tags")] + + ### RELATIONS + + parent_page_types = ["region.RegionArticlesPage"] + subpage_types = [] + + ### OTHERS + + class Meta: + verbose_name = "Aktualita" + + +class RegionArticlesPage(SubpageMixin, MetadataPageMixin, Page): + ### FIELDS + + max_items = models.IntegerField("Počet článků na stránce", default=12) + + ### PANELS + + content_panels = Page.content_panels + [ + FieldPanel("max_items"), + ] + + settings_panels = [CommentPanel()] + + ### RELATIONS + + parent_page_types = ["region.RegionHomePage"] + subpage_types = ["region.RegionArticlePage"] + + ### OTHERS + + class Meta: + verbose_name = "Aktuality" + + def get_context(self, request): + context = super().get_context(request) + context["articles"] = Paginator( + self.get_children().live().specific(), + self.max_items, + ).get_page(request.GET.get("page")) + return context + + +class RegionContactPage(SubpageMixin, MetadataPageMixin, Page): + class ContactItemBlock(blocks.StructBlock): + name = blocks.CharBlock(label="Role") + person = blocks.PageChooserBlock( + label="Osoba", + page_type=["region.RegionPersonPage"], + ) + + class Meta: + label = "Kontakt" + + ### FIELDS + + contact_people = StreamField( + [("item", ContactItemBlock())], + verbose_name="Kontakty", + blank=True, + ) + text = RichTextField("Text", blank=True, features=RICH_TEXT_FEATURES) + + ### PANELS + + content_panels = Page.content_panels + [ + StreamFieldPanel("contact_people"), + FieldPanel("text"), + ] + + ### RELATIONS + + parent_page_types = ["region.RegionHomePage"] + subpage_types = [] + + ### OTHERS + + class Meta: + verbose_name = "Kontakty" + + +class RegionTagsPage(SubpageMixin, MetadataPageMixin, Page): + ### PANELS + + settings_panels = [CommentPanel()] + + ### RELATIONS + + parent_page_types = ["region.RegionHomePage"] + subpage_types = [] + + ### OTHERS + + class Meta: + verbose_name = "Stránka s tagy" + + def get_context(self, request): + context = super().get_context(request) + + # Natrid clanky do hashtable dle tagu (v template by se to delalo podstatne hur) + tags = {} + for x in self.root_page.articles_page.get_children().live().specific(): + for y in x.tags.all(): + try: + tags[y.name].append(x) + except KeyError: + tags[y.name] = [x] + + context["tags"] = tags + return context + + +class RegionPersonPage(SubpageMixin, MetadataPageMixin, Page): + ### FIELDS + + person = models.ForeignKey(Person, on_delete=models.PROTECT, null=True) + perex = models.TextField("Perex osoby", blank=True) + + ### PANELS + + content_panels = Page.content_panels + [ + # InlinePanel("person"), + FieldPanel("perex"), + ] + + ### RELATIONS + + parent_page_types = ["region.RegionPeoplePage"] + subpage_types = [] + + ### OTHERS + + class Meta: + verbose_name = "Detail osoby" + + @property + def pageperex(self): + """Vraci perex Pirata nejblizzsi lokalnimu kontextu. + Zamerne jiny nazev, aby v template bylo na vyber z x.perex, x.person.perex a x.pageperex + """ + return self.perex or self.person.perex + + def get_context(self, request): + context = super().get_context(request) + # Na strance detailu cloveka se vpravo zobrazuji 3 dalsi nahodne profily + context["random_people"] = list( + self.get_siblings(inclusive=False).live().specific() + ) + random.shuffle(context["random_people"]) + context["random_people"] = context["random_people"][:3] + return context + + +class RegionPeoplePage(SubpageMixin, MetadataPageMixin, Page): + settings_panels = [CommentPanel()] + + ### RELATIONS + + parent_page_types = ["region.RegionHomePage"] + subpage_types = ["region.RegionPersonPage"] + + ### OTHERS + + class Meta: + verbose_name = "Lidé" -# Create your models here. + def get_context(self, request): + context = super().get_context(request) + context["people"] = self.get_children().live().specific() + return context diff --git a/region/templates/region/base.html b/region/templates/region/base.html new file mode 100644 index 00000000..64e6fd8d --- /dev/null +++ b/region/templates/region/base.html @@ -0,0 +1,286 @@ +{% load static wagtailcore_tags wagtailimages_tags wagtailmetadata_tags %} +<!doctype html> +<html lang="cs"> +<head> + <!-- Meta --> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width" /> + {% meta_tags %} + {% if settings.MAJAK_ENV == "test" %} + <meta name="robots" content="noindex, nofollow"> + {% endif %} + + <!-- Favicon --> + {% include "shared/favicon_snippet.html" %} + + <!-- Bootstrap CSS --> + + <!-- Styles --> + <link rel="stylesheet" href="{% static "styleguide18/assets/css/styles.css" %}"> + + <style type="text/css"> + .inline-block { + display: inline-block; + } + </style> + + {% if page.root_page.matomo_id %} + {% include "shared/matomo_snippet.html" with matomo_id=page.root_page.matomo_id %} + {% endif %} +</head> + +<body> + + <nav class="navbar __js-root py-lg-6"> + <ui-app inline-template> + <ui-navbar inline-template> + <div> + <div class="container container--wide navbar__content" :class="{'navbar__content--initialized': true}"> + + <div class="navbar__brand my-4 flex items-center lg:block lg:pr-8 lg:my-0"> + <a href="/"> + <img src="{% static "styleguide18/assets/images/logo-round-white.svg" %}" class="w-10 lg:w-full lg:border-r lg:border-grey-300 lg:pr-8" /> + </a> + <span class="lg:hidden pl-4 font-bold text-xl">Pirátská strana</span> + </div> + + <div class="navbar__menutoggle my-4 flex justify-end lg:hidden"> + <a href="#" @click="show = !show" class="no-underline hover:no-underline"> + <i class="ico--menu text-3xl"></i> + </a> + </div> + + <div v-if="show || isLgScreenSize" class="navbar__external navbar__section navbar__section--expandable container-padding--zero lg:container-padding--auto lg:flex lg:space-x-8 lg:pb-2"> + + <div class="text-grey-200 text-sm lg:space-x-8 leading-loose lg:leading-normal"> + + <a href="https://www.pirati.cz" class="contact-line icon-link content-block--nostyle block lg:inline-block" target="_blank" rel="noopener noreferrer"> + <i class="ico--home"></i> + <span>pirati.cz</span> + </a> + + <a href="https://piratskyobchod.cz" class="contact-line icon-link content-block--nostyle block lg:inline-block" target="_blank" rel="noopener noreferrer"> + <i class="ico--cart"></i> + <span>piratskyobchod.cz</span> + </a> + + <a href="http://www.piratskelisty.cz" class="contact-line icon-link content-block--nostyle block lg:inline-block" target="_blank" rel="noopener noreferrer"> + <i class="ico--newspaper"></i> + <span>Pirátské listy</span> + </a> + + </div> + + <div class="social-icon-group space-x-2 text-grey-200 py-4 lg:py-0"> + {% include "shared/social_icons_snippet.html" %} + </div> + + </div> + + <div v-if="show || isLgScreenSize" class="navbar__main navbar__section navbar__section--expandable container-padding--zero lg:container-padding--auto"> + <ul class="navbar-menu text-white"> + <li class="navbar-menu__item"><a href="{% pageurl page.root_page.articles_page %}" class="navbar-menu__link">{{ page.root_page.articles_page }}</a></li> + <li class="navbar-menu__item"><a href="{% pageurl page.root_page.people_page %}" class="navbar-menu__link">{{ page.root_page.people_page }}</a></li> + {% comment %} + <li class="navbar-menu__item"><a href="/komunalni-program/" class="navbar-menu__link">Komunální program</a></li> + {% endcomment %} + <li class="navbar-menu__item"><a href="{% pageurl page.root_page.contact_page %}" class="navbar-menu__link">{{ page.root_page.contact_page }}</a></li> + </ul> + </div> + + <div v-if="show || isLgScreenSize" class="navbar__actions navbar__section navbar__section--expandable container-padding--zero lg:container-padding--auto self-start flex flex-col sm:flex-row lg:flex-col sm:space-x-4 space-y-2 sm:space-y-0 lg:space-y-2 xl:flex-row xl:space-x-2 xl:space-y-0"> + <a href="https://dary.pirati.cz/projekty-kampane/zlk-potrebuje-peci/" rel="noopener noreferrer" target="_blank" class="btn btn--icon btn--cyan-200 btn--hoveractive btn--condensed btn--fullwidth md:btn--autowidth lg:text-sm xl:text-base"> + <div class="btn__body-wrap"> + <div class="btn__body ">Přispěj</div> + <div class="btn__icon "> + <i class="ico--pig"></i> + </div> + </div> + </a> + <a href="https://nalodeni.pirati.cz" rel="noopener noreferrer" target="_blank" class="btn btn--icon btn--blue-300 btn--hoveractive btn--condensed btn--fullwidth md:btn--autowidth lg:text-sm xl:text-base"> + <div class="btn__body-wrap"> + <div class="btn__body ">Naloď se</div> + <div class="btn__icon "> + <i class="ico--anchor"></i> + </div> + </div> + </a> + </div> + </div> + </div> + </ui-navbar> + </ui-app> +</nav> + +<div class="__js-root"> + <ui-app inline-template> + + <ui-view-provider :initial="{regions: false, calendar: false}" v-slot="{ isCurrentView, toggleView }"> + <nav class="subnav py-2"> + <div class="container container--wide"> + <div class="flex"> + + {% comment %} + <button @click="toggleView('regions')" class="btn btn--condensed btn--grey-500 btn--hoveractive btn--to-white text-sm mr-2 px-0" :class="{'btn--activated': isCurrentView('regions')}"> + <div class="btn__body py-2"> + <span>Piráti v dalších krajích</span> + <i class="ico--chevron-down ml-4"></i> + </div> + </button> + + <button @click="toggleView('calendar')" class="btn btn--inline-icon btn--condensed btn--hoveractive btn--grey-500 btn--to-orange-300 text-sm px-0" :class="{'btn--activated': isCurrentView('calendar')}"> + <div class="btn__body py-2"> + <i class="btn__inline-icon ico--calendar mr-0 md:mr-2 text-orange-300"></i> + <span class="hidden md:block">Krajský kalendář</span> + </div> + </button> + {% endcomment %} + + {% if page.root_page.facebook %} + <a href="{{ page.root_page.facebook }}" target="_blank" rel="noopener noreferrer" class="btn btn--inline-icon btn--condensed btn--hoveractive btn--grey-500 btn--to-brands-facebook text-sm ml-2 px-0"> + <div class="btn__body py-2"> + <i class="btn__inline-icon ico--facebook mr-0 md:mr-2 text-brands-facebook"></i> + <span class="hidden md:block">{{ page.root_page }}</span> + </div> + </a> + {% endif %} + + </div> + </div> + </nav> + + <aside class="subnav-aside"> + <div class="subnav-aside__item" :class="{'subnav-aside__item--visible': isCurrentView('regions')}"> + <a @click="toggleView('regions')" class="subnav-aside__close"><i class="ico--close"></i></a> + <ui-region-map class="container container--default" /> + </div> + <div class="subnav-aside__item" :class="{'subnav-aside__item--visible': isCurrentView('calendar')}"> + <a @click="toggleView('calendar')" class="subnav-aside__close"><i class="ico--close"></i></a> + <div class="container container--default"> + + <iframe src="https://calendar.google.com/calendar/embed?showTitle=0&showNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&showTz=0&mode=AGENDA&height=500&wkst=2&hl=cs&bgcolor=%23FFFFFF&src=kddvdvu3adcjef2kro4j6mm838%40group.calendar.google.com&color=%232952A3&ctz=Europe%2FPrague" style="border-width:0; width: 100%; height: 410px; border: 0; overflow: hidden;"></iframe> + <p class="mt-4"> + <a class="btn btn--orange-200 btn--hoveractive" href="https://calendar.google.com/calendar/embed?showTitle=0&showNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&showTz=0&mode=AGENDA&height=500&wkst=2&hl=cs&bgcolor=%23FFFFFF&src=kddvdvu3adcjef2kro4j6mm838%40group.calendar.google.com&color=%232952A3&ctz=Europe%2FPrague"> + <span class="btn__body">Zobrazit všechny akce</span> + </a> + </p> + + </div> + </div> + </aside> + </ui-view-provider> + + + </ui-app> +</div> + + + {% block subheader %}{% endblock %} + <div class="container container--default lg:py-4"> + {% block content %}{% endblock %} + </div> + + + <footer class="footer bg-grey-700 text-white __js-root"> + + <ui-app inline-template> + + <div> + <div class="footer__main py-4 lg:py-16 container container--default pt-5"> + + <section class="footer__brand"> + <img src="{% static "shared/img/logo-full-white.svg" %}" alt="Pirátská strana" class="w-32 md:w-40 pb-6" /> + <p class="para hidden md:block md:mb-4 lg:mb-0 text-grey-200"> + Piráti, {% now "Y" %}. Všechna práva vyhlazena. + Sdílejte a nechte ostatní sdílet za stejných podmínek. + </p> + </section> + + <section class="footer__main-links bg-grey-700 text-white lg:grid grid-cols-3 gap-4"> + <div class="pb-4"> + <ui-footer-collapsible label="Připoj se"> + <ul class="mt-6 space-y-2 text-grey-200"> + <li><a href="{{ page.root_page.contact_newcomers|default:"https://nalodeni.pirati.cz" }}">Zájemci o členství</a></li> + <li><a href="{{ page.root_page.contact_page.url }}">Dej nám vědět</a></li> + <li><a href="https://nalodeni.pirati.cz">Nalodění</a></li> + </ul> + </ui-footer-collapsible> + </div> + + <div class="pb-4 border-t border-grey-400 lg:border-t-0"> + <ui-footer-collapsible label="Makáme"> + <ul class="mt-6 space-y-2 text-grey-200"> + <li><a href="{{ page.root_page.people_page.url }}">{{ page.root_page.people_page }}</a></li> + <li><a href="{{ page.root_page.articles_page.url }}">{{ page.root_page.articles_page }}</a></li> + </ul> + </ui-footer-collapsible> + </div> + + <div class="pb-4 border-t border-grey-400 lg:border-t-0"> + <ui-footer-collapsible label="Otevřenost"> + <ul class="mt-6 space-y-2 text-grey-200"> + <li><a href="https://ucet.pirati.cz">Transparentní účet</a></li> + <li><a href="https://smlouvy.pirati.cz">Registr smluv</a></li> + <li><a href="https://wiki.pirati.cz/fo/otevrene_ucetnictvi">Otevřené účetnictví</a></li> + </ul> + </ui-footer-collapsible> + </div> + </section> + + <section class="footer__social lg:text-right"> + <div class="mb-4"> + <div class="social-icon-group space-x-2 text-white pb-4"> + {% include "shared/social_icons_snippet.html" %} + </div> + <a href="mailto:{{ page.root_page.contact_email|default:"info@pirati.cz" }}" class="contact-line icon-link content-block--nostyle " ><i class="ico--envelope"></i><span>Dejte nám vědět</span></a> + </div> + + <div class="flex flex-col md:flex-row lg:flex-col lg:items-end space-y-2 lg:space-x-0 mr-0 pr-0"> + + <a href="{{ page.root_page.donation_page|default:"https://dary.pirati.cz" }}" rel="noopener noreferrer" target="_blank" class="btn btn--icon btn--cyan-200 btn--hoveractive text-lg btn--fullwidth sm:btn--autowidth px-0 mx-0"> + <div class="btn__body-wrap"> + <div class="btn__body ">Přispěj</div> + <div class="btn__icon "><i class="ico--pig"></i></div> + </div> + </a> + + <a href="https://nalodeni.pirati.cz" rel="noopener noreferrer" target="_blank" class="btn btn--icon btn--blue-300 btn--hoveractive text-lg btn--fullwidth sm:btn--autowidth mt-0 px-0 mx-0"> + <div class="btn__body-wrap"> + <div class="btn__body ">Naloď se</div> + <div class="btn__icon "><i class="ico--anchor"></i></div> + </div> + </a> + + </div> + + </section> + </div> + + <section class="bg-black py-4 lg:py-12"> + <div class="container container--default"> + <div class="grid gap-4 grid-cols-1 md:grid-cols-2 xl:grid-cols-3"> + {% if page.root_page.footperson_coord %} + {% include "shared/person_badge_snippet.html" with person=page.root_page.footperson_coord title="Koordinátor" %} + {% endif %} + {% if page.root_page.footperson_electman %} + {% include "shared/person_badge_snippet.html" with person=page.root_page.footperson_electman title="Volební manažer" %} + {% endif %} + {% if page.root_page.footperson_media %} + {% include "shared/person_badge_snippet.html" with person=page.root_page.footperson_media title="Kontakt pro média" %} + {% endif %} + </div> + </div> + </section> + + </div> + </ui-app> +</footer> + + + <script src="{% static "styleguide18/assets/js/vue.2.6.11.js" %}"></script> + <script src="{% static "styleguide18/assets/js/main.bundle.js" %}"></script> + <script src="{% static "shared/vendor/jquery/jquery-3.4.1.min.js" %}"></script> + <script src="{% static "shared/vendor/lazysizes/lazysizes.min.js" %}"></script> + <script src="{% static "shared/vendor/fancybox/jquery.fancybox.min.js" %}"></script> +</body> +</html> diff --git a/region/templates/region/region_article_page.html b/region/templates/region/region_article_page.html new file mode 100644 index 00000000..b7652255 --- /dev/null +++ b/region/templates/region/region_article_page.html @@ -0,0 +1,83 @@ +{% extends "region/base.html" %} +{% load static wagtailcore_tags wagtailimages_tags %} + +{% block content %} + +<div class="container container--default py-8 lg:py-24"> + + <article itemtype="http://schema.org/BlogPosting" itemscope=""> + + <header> + <link itemprop="mainEntityOfPage" href="{{ page.url }}"> + <meta itemprop="datePublished" content="{{ page.last_published_at }}"> + <meta itemprop="dateModified" content=""> + + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-4">{{ page.title }}</h1> + + <div class="flex flex-col md:flex-row md:items-center"> + + <div class="inline-flex divide-x flex-grow"> + <span class="pr-2">{{ page.date|date:"SHORT_DATE_FORMAT" }}</span> + <span class="pl-2" itemprop="author" itemtype="http://schema.org/Person" itemscope=""> + <span itemprop="name">{{ page.author }}</span> + </span> + </div> + + <div class="my-4"> + {% for tag in page.tags.all %} + <a href="{{ page.root_page.tags_page.url }}#{{ tag}}" class="btn btn--grey-125 btn--condensed" ><div class="btn__body ">{{ tag }}</div></a> + {% endfor %} + </div> + + </div> + + <figure class="figure"> + {% image page.image width-2000 as img %} + <img src="{{ img.url }}" alt="{{ page.title }}" /> + </figure> + + </header> + + <div class="lg:flex mt-8 lg:space-x-16"> + + <div class="lg:w-2/3"> + <div itemprop="description" class="w-full content-block"> + {{ page.text|richtext }} + </div> + </div> + + <div class="pt-8 lg:w-1/3 md:pt-0"> + <div class="space-y-8"> + <div class="sharebox md:card md:elevation-10 "> + <div class="md:card__body"> + <span class="head-alt-base md:head-alt-md">Sdílení je aktem lásky</span> + <div class="flex w-full space-x-4 pt-4 md:pt-8 text-center text-white"> + <a + href="https://www.facebook.com/sharer/sharer.php?u={{ page.full_url|urlencode }}" + onclick="window.open(this.href, 'pop-up', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0'); return false;" + class="bg-brands-facebook px-8 py-3 text-2xl w-full" + ><i class="ico--facebook"></i></a> + <a + href="https://twitter.com/intent/tweet?text={{ page.title|urlencode }}&url={{ page.full_url|urlencode }}" + onclick="window.open(this.href, 'pop-up', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0'); return false;" + class="bg-brands-twitter px-8 py-3 text-2xl w-full" + ><i class="ico--twitter"></i></a> + </div> + </div> + <div class="h-52 overflow-hidden hidden md:block"> + <img src="{% static "shared/img/flag.png" %}" alt="Pirátská strana" class="w-80 object-cover m-auto" /> + </div> + </div> + + </div> + </div> + + </div> + </article> + +</div> + +{% include "shared/more_articles_snippet.html" %} + + +{% endblock %} diff --git a/region/templates/region/region_articles_page.html b/region/templates/region/region_articles_page.html new file mode 100644 index 00000000..aa7178f4 --- /dev/null +++ b/region/templates/region/region_articles_page.html @@ -0,0 +1,54 @@ +{% extends "region/base.html" %} + +{% block content %} +<main> + + <div class="container container--default py-8 lg:py-24"> + + <header> + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> + </header> + + <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8"> + {% for a in articles %} + {% include "shared/article_preview.html" with article=a %} + {% endfor %} + </div> + + <div class="pagination-container" role="navigation" aria-label="Pagination"> + <nav> + + {% if articles.has_previous %} + <a href="{{ page.root_page.articles_page.url }}?page={{ articles.previous_page_number }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed btn--inverted-icon px-0" aria-label="Předchozí stránka"> + <div class="btn__body-wrap"> + <div class="btn__body ">Předchozí</div> + <div class="btn__icon "> + <i class="ico--chevron-left"></i> + </div> + </div> + </a> + {% endif %} + + {% for i in articles.paginator.page_range %} + <a href="{{ page.root_page.articles_page.url }}?page={{ i }}" class="btn {% if i == articles.number %} btn--grey-500 {% else %} btn--grey-125 {% endif %} btn--hoveractive btn--to-black btn--condensed hidden md:inline-block px-0" aria-label="Stránka {{ i }}"> + <div class="btn__body ">{{ i }}</div> + </a> + {% endfor %} + + {% if articles.has_next %} + <a href="{{ page.root_page.articles_page.url }}?page={{ articles.next_page_number }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed px-0" aria-label="Další stránka"> + <div class="btn__body-wrap"> + <div class="btn__body ">Další</div> + <div class="btn__icon "> + <i class="ico--chevron-right"></i> + </div> + </div> + </a> + {% endif %} + + </nav> + </div> + </div> + +</main> +{% endblock %} diff --git a/region/templates/region/region_contact_page.html b/region/templates/region/region_contact_page.html new file mode 100644 index 00000000..eaab2163 --- /dev/null +++ b/region/templates/region/region_contact_page.html @@ -0,0 +1,88 @@ +{% extends "region/base.html" %} +{% load wagtailcore_tags wagtailimages_tags shared_filters %} + +{% block content %} + + <div class="container container--default py-8"> + <div class="lg:flex lg:mt-8 space-y-16 lg:space-y-0 lg:space-x-8 xl:space-x-16 mb-5"> + <section class="lg:w-3/5 xl:w-2/3"> + + <header> + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> + </header> + + {% for item in page.contact_people %} + + <div> + <h2 class="head-heavy-sm mb-2 lg:mb-4 mt-4">{{ item.value.name }}</h2> + <div class="card elevation-3 p-3 mb-3"> + {% include "shared/person_badge_snippet.html" with person=item.value.person %} + </div> + </div> + + {% endfor %} + + <div class="content-block"> + {{ page.text | richtext }} + </div> + + </section> + + <section class="lg:w-2/5 xl:w-1/3 lg:pt-0"> + <div class="lg:card lg:elevation-10"> + <div class="lg:card__body content-block"> + + <h2>Základní údaje</h2> + + <div class="space-y-4"> + <div> + <h4>Emailová adresa</h4> + <a href="mailto:yveta.martinkova@pirati.cz" class="contact-line icon-link content-block--nostyle "> + <i class="ico--envelope"></i><span>{{ page.root_page.contact_email }}</span> + </a> + </div> + + <div> + <h4>Telefonický kontakt</h4> + <a href="tel:{{ page.root_page.contact_phone }}" class="contact-line icon-link content-block--nostyle "> + <i class="ico--phone"></i><span>{{ page.root_page.contact_phone }}</span> + </a> + </div> + + <div> + <h4>Transparentní účty</h4> + 2100048174/2010 a <a href="https://wiki.pirati.cz/fo/seznam_uctu">další účty</a> + </div> + + <div> + <h4>Datová schránka</h4> + <span class="contact-line icon-link content-block--nostyle "> + <i class="ico--drawer"></i><span>b2i4r6j</span></span> + </div> + + <div> + <h4>Celostátní web</h4> + <a href="https://www.pirati.cz" class="contact-line icon-link content-block--nostyle "> + <i class="ico--pirati"></i><span>www.pirati.cz</span> + </a> + </div> + + <p>Každý člen strany má email ve tvaru: <tt>jmeno.prijmeni@pirati.cz</tt></p> + + </div> + + <hr class="hr"> + + <h2>Sídlo a kontaktní centrum</h2> + <strong>Piráti Zlínský kraj</strong> + + </div> + </div> + </section> + </div> + + {% include "shared/followus_snippet.html" %} + + </div> + +{% endblock %} diff --git a/region/templates/region/region_home_page.html b/region/templates/region/region_home_page.html new file mode 100644 index 00000000..1b9f7036 --- /dev/null +++ b/region/templates/region/region_home_page.html @@ -0,0 +1,20 @@ +{% extends "region/base.html" %} +{% load wagtailcore_tags %} + +{% block content %} +<main> + + <h1 class="head-alt-md md:head-alt-lg pb-4 lg:pb-8 pt-5">Aktuální témata</h1> + + <!-- list of articles --> + <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8"> + {% for a in page.articles %} + {% include "shared/article_preview.html" with article=a %} + {% endfor %} + </div> + + {% include "shared/more_articles_snippet.html" %} + {% include "shared/followus_snippet.html" %} + +</main> +{% endblock %} diff --git a/region/templates/region/region_people_page.html b/region/templates/region/region_people_page.html new file mode 100644 index 00000000..49cad809 --- /dev/null +++ b/region/templates/region/region_people_page.html @@ -0,0 +1,22 @@ +{% extends "region/base.html" %} +{% load wagtailcore_tags wagtailimages_tags shared_filters %} + +{% block content %} + +<div class="container container--default py-8 lg:py-24"> + + <header> + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1> + </header> + + <h2 class="head-heavy-base mb-4">Členové a příznivci</h2> + + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 row-gap-8 col-gap-8"> + {% for person in people %} + {% include "shared/person_badge_snippet.html" with person=person %} + {% endfor %} + </div> + +</div> + +{% endblock %} diff --git a/region/templates/region/region_person_page.html b/region/templates/region/region_person_page.html new file mode 100644 index 00000000..13cde222 --- /dev/null +++ b/region/templates/region/region_person_page.html @@ -0,0 +1,104 @@ +{% extends "region/base.html" %} +{% load wagtailcore_tags wagtailimages_tags shared_filters %} + +{% block subheader %} + +<header class="hero hero--image pt-16 pb-24 lg:pt-32 pb-24 candidate-detail__hero" + style="--image-url: url(https://roznov.pirati.cz/assets/articles/2020/kampan20/zahajenikampan1-067fb446ec8933ae14591cbc29fc53ebb3009e4185900838bfb94752addbfa7b.jpg)" +> + + <div class="container container--default py-2"> + <h1 class="head-alt-md md:head-alt-lg max-w-2xl text-left lg:text-left px-4"> + <span class="academic-title-name">{{ page.name }}</span> + </h1> + <h2 class="head-xs mt-2 max-w-xl mx-auto text-center lg:text-left"></h2> + </div> +</header> + +{% endblock %} + +{% block content %} + +<div class="container container--default py-8 lg:pb-24"> + + <main> + <div class="flex flex-col lg:flex-row lg:space-x-8 xl:space-x-16"> + + <section class="lg:w-3/5 xl:w-2/3"> + <div class="content-block w-full"> + {{ page.longtext }} + </div> + </section> + + <section class="lg:w-2/5 xl:w-1/3 pt-8 lg:pt-0 order-first lg:order-last candidate-detail__sidebar"> + <aside class="container-padding--zero lg:container-padding--auto lg:card lg:elevation-10"> + <div class="lg:card__body p-4 lg:p-8"> + + <div class="text-center mb-8"> + <div class="avatar avatar--2xl lg:avatar--3xl avatar--bordered candidate-detail__avatar"> + <img src="{{ page.portrait }}" alt="" /> + </div> + </div> + + {% if page.facebook %} + <div class="flex flex-wrap item-center"> + <div class="social-icon-group space-x-0/5"> + <a class="social-icon" target="_blank" rel="noreferrer noopener" href="{{ page.facebook }}"><i class="ico--facebook"></i></a> + </div> + </div> + {% endif %} + + <div class="content-block"> + <hr /> + <div class="space-y-4"> + {% if page.phone %} + <div> + <h4>Telefon</h4> + <a href="tel:{{ page.phone }}" class="contact-line icon-link content-block--nostyle " > + <i class="ico--phone"></i><span>{{ page.phone }}</span> + </a> + </div> + {% endif %} + <div> + <h4>Email</h4> + <a href="mailto:{{ page.email }}" class="contact-line icon-link content-block--nostyle " > + <i class="ico--envelope"></i><span>{{ page.email }}</span> + </a> + </div> + </div> + </div> + + <hr /> + + <div class="hidden lg:block"> + + <div class="content-block"> + <h2>Lidé</h2> + </div> + + <div class="space-y-4"> + {% for person in random_people %} + {% include "shared/person_badge_snippet.html" with person=person skipcontacts=1 %} + {% endfor %} + </div> + + <a href="{{ page.root_page.people_page.url }}" class="btn btn--icon btn--violet-500 btn--fullwidth btn--hoveractive pt-4" > + <div class="btn__body-wrap"> + <div class="btn__body ">Poznejte celý náš tým</div> + <div class="btn__icon "> + <i class="ico--chevron-right"></i> + </div> + </div> + </a> + + </div> + + </div> +</aside> + </section> + + </div> + </main> +</div> + +{% endblock %} diff --git a/region/templates/region/region_program_page.html b/region/templates/region/region_program_page.html new file mode 100644 index 00000000..2bbc41fa --- /dev/null +++ b/region/templates/region/region_program_page.html @@ -0,0 +1,33 @@ +{% extends "region/base.html" %} +{% load wagtailcore_tags wagtailimages_tags shared_filters %} + +{% block content %} + + <div class="container container--default py-8"> + <div class="lg:flex lg:mt-8 space-y-16 lg:space-y-0 lg:space-x-8 xl:space-x-16 mb-5"> + <section> + + <header> + <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8"> + {{ page.title }} + </h1> + </header> + + <p> + {{ page.perex }} + </p> + +{# {{ page.content }}#} + + {% for block in page.content %} + + {% include_block block %} + + {% endfor %} + + </section> + + </div> + </div> + +{% endblock %} diff --git a/region/templates/region/region_tags_page.html b/region/templates/region/region_tags_page.html new file mode 100644 index 00000000..5d07b0ff --- /dev/null +++ b/region/templates/region/region_tags_page.html @@ -0,0 +1,26 @@ +{% extends "region/base.html" %} + +{% block content %} +<main> + + <h1 class="head-alt-md md:head-alt-lg max-w-5xl mb-4 mt-5">{{ page }}</h1> + + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> + {% for tag, articles in tags.items %} + + <section class="card"> + <div class="card__body p-4"> + <h3 class="head-heavy-xs mb-2" id="{{ tag }}">{{ tag }}</h3> + <ul class="unordered-list unordered-list--linked unordered-list--dense leading-normal font-light text-sm"> + {% for x in articles %} + <li><a href="{{ x.url }}">{{ x }}</a></li> + {% endfor %} + </ul> + </div> + </section> + + {% endfor %} + </div> + +</main> +{% endblock %} diff --git a/shared/templates/shared/article_preview.html b/shared/templates/shared/article_preview.html index 953dbc43..1ada7699 100644 --- a/shared/templates/shared/article_preview.html +++ b/shared/templates/shared/article_preview.html @@ -47,7 +47,10 @@ <p class="card-body-text flex-grow">{{article.perex}}</p> <div class="inline-block-nogap mt-4"> {% for tag in article.tags.all %} - <a href="{{ page.root_page.tags_page.url }}#{{ tag }}" class="btn article-card__category-button btn--condensed text-sm font-light btn--grey-700 p-0" > + <a + href="{{ page.root_page.tags_page.url }}?tag={{ tag.slug }}" + class="btn article-card__category-button btn--condensed text-sm font-light btn--grey-125 btn--hoveractive" + > <div class="btn__body">{{ tag }}</div> </a> {% endfor %} diff --git a/shared/templates/shared/followus_snippet.html b/shared/templates/shared/followus_snippet.html new file mode 100644 index 00000000..59181100 --- /dev/null +++ b/shared/templates/shared/followus_snippet.html @@ -0,0 +1,13 @@ +<div class="flex flex-col lg:flex-row lg:space-x-8"> + <a href="{{ 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 }}" + 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> + </a> +</div> diff --git a/district/templates/district/more_articles_snippet.html b/shared/templates/shared/more_articles_snippet.html similarity index 100% rename from district/templates/district/more_articles_snippet.html rename to shared/templates/shared/more_articles_snippet.html diff --git a/shared/templates/shared/social_icons_snippet.html b/shared/templates/shared/social_icons_snippet.html new file mode 100644 index 00000000..dbcf521c --- /dev/null +++ b/shared/templates/shared/social_icons_snippet.html @@ -0,0 +1,6 @@ +<a href="{{ page.root_page.twitter|default:"https://www.twitter.com/PiratskaStrana" }}" rel="noopener noreferrer" target="_blank" title="Náš účet na Twitteru" class="social-icon "><i class="ico--twitter"></i></a> +<a href="{{ page.root_page.youtube|default:"https://www.youtube.com/channel/UC_zxYLGrkmrYazYt0MzyVlA" }}" rel="noopener noreferrer" target="_blank" title="Náš účet na YouTube" class="social-icon "><i class="ico--youtube"></i></a> +<a href="/feed.xml" rel="noopener noreferrer" target="_blank" title="Články tohoto webu v RSS" class="social-icon "><i class="ico--feed"></i></a> +<a href=https://www.instagram.com/pirati.cz/" rel="noopener noreferrer" target="_blank" title="Instagram - Česká pirátská strana" class="social-icon "><i class="ico--instagram"></i></a> +<a href=https://www.flickr.com/photos/pirati/" rel="noopener noreferrer" target="_blank" title="Flickr - Česká pirátská strana" class="social-icon "><i class="ico--flickr"></i></a> +<a href="mailto:{{ page.root_page.contact_email|default:"info@pirati.cz" }}" class="social-icon "><i class="ico--envelope"></i></a> diff --git a/shared/templates/styleguide/2.3.x/pagination.html b/shared/templates/styleguide/2.3.x/pagination.html index 967622a3..c6da34ae 100644 --- a/shared/templates/styleguide/2.3.x/pagination.html +++ b/shared/templates/styleguide/2.3.x/pagination.html @@ -4,7 +4,7 @@ <nav class="pagination space-x-1"> {% if paginator.has_previous %} - <a href="{% pageurl page %}?page={{ paginator.previous_page_number }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed btn--inverted-icon"> + <a href="{% pageurl page %}?page={{ paginator.previous_page_number }}{{ extra_query }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed btn--inverted-icon"> <div class="btn__body-wrap"> <div class="btn__body ">předchozí</div> <div class="btn__icon "> @@ -16,16 +16,16 @@ {% for i in paginator.paginator.page_range %} {% if i == paginator.number %} - <a href="{% pageurl page %}?page={{ i }}" class="btn btn--grey-500 btn--condensed hidden md:inline-block"> + <a href="{% pageurl page %}?page={{ i }}{{ extra_query }}" class="btn btn--grey-500 btn--condensed hidden md:inline-block"> {% else %} - <a href="{% pageurl page %}?page={{ i }}" class="btn btn--grey-125 btn--hoveractive btn--to-black btn--condensed hidden md:inline-block"> + <a href="{% pageurl page %}?page={{ i }}{{ extra_query }}" class="btn btn--grey-125 btn--hoveractive btn--to-black btn--condensed hidden md:inline-block"> {% endif %} <div class="btn__body ">{{ i }}</div> </a> {% endfor %} {% if paginator.has_next %} - <a href="{% pageurl page %}?page={{ paginator.next_page_number }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed"> + <a href="{% pageurl page %}?page={{ paginator.next_page_number }}{{ extra_query }}" class="btn btn--icon btn--grey-125 btn--hoveractive btn--to-black btn--condensed"> <div class="btn__body-wrap"> <div class="btn__body ">další</div> <div class="btn__icon "> -- GitLab