diff --git a/elections/migrations/0022_alter_electionshomepage_content_and_more.py b/elections/migrations/0022_alter_electionshomepage_content_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..b069f638e519f7f49955cc65142de710c2b65028 --- /dev/null +++ b/elections/migrations/0022_alter_electionshomepage_content_and_more.py @@ -0,0 +1,359 @@ +# Generated by Django 4.1.13 on 2024-03-12 15:21 + +import django.db.models.deletion +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks +import wagtailmetadata.models +from django.db import migrations, models + +import shared.models.base + + +class Migration(migrations.Migration): + dependencies = [ + ("wagtailimages", "0025_alter_image_file_alter_rendition_file"), + ("wagtailcore", "0083_workflowcontenttype"), + ("elections", "0021_alter_electionshomepage_content"), + ] + + operations = [ + migrations.AlterField( + model_name="electionshomepage", + name="content", + field=wagtail.fields.StreamField( + [ + ( + "carousel", + wagtail.blocks.StructBlock( + [ + ( + "desktop_image", + wagtail.images.blocks.ImageChooserBlock( + help_text="Pokud není vybráno video, ukáže se na desktopu.", + label="Obrázek na pozadí (desktop)", + ), + ), + ( + "mobile_image", + wagtail.images.blocks.ImageChooserBlock( + help_text="Pokud je vybrán, ukáže se místo videa na mobilu.", + label="Obrázek (mobil)", + required=False, + ), + ), + ( + "video_url", + wagtail.blocks.URLBlock( + help_text="Pokud je vybráno, ukáže se na desktopech s povoleným autoplayem místo obrázku.", + label="URL videa", + required=False, + ), + ), + ( + "mobile_line_1", + wagtail.blocks.TextBlock( + label="První mobilní řádek" + ), + ), + ( + "mobile_line_2", + wagtail.blocks.TextBlock( + label="Druhý mobilní řádek" + ), + ), + ] + ), + ), + ( + "candidates", + wagtail.blocks.StructBlock( + [ + ( + "candidates", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "page", + wagtail.blocks.PageChooserBlock( + label="Stránka", + page_type=[ + "elections.ElectionsCandidatePage" + ], + ), + ), + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + help_text="Pokud není vybrán, použije se obrázek ze stránky kandidáta", + label="Obrázek", + required=False, + ), + ), + ( + "description", + wagtail.blocks.TextBlock( + label="Popis" + ), + ), + ] + ), + label="Kandidáti", + ), + ) + ] + ), + ), + ( + "secondary_candidates", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(label="Nadpis")), + ( + "candidates", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "number", + wagtail.blocks.CharBlock( + label="Číslo" + ), + ), + ( + "page", + wagtail.blocks.PageChooserBlock( + label="Stránka", + page_type=[ + "elections.ElectionsCandidatePage" + ], + ), + ), + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + help_text="Pokud není vybrán, použije se obrázek ze stránky kandidáta", + label="Obrázek", + required=False, + ), + ), + ] + ), + label="Kandidáti", + ), + ), + ] + ), + ), + ( + "program", + wagtail.blocks.StructBlock( + [ + ( + "label", + wagtail.blocks.CharBlock( + default="Program", + help_text="Např. 'Program'", + label="Nadpis", + ), + ), + ( + "categories", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "number", + wagtail.blocks.IntegerBlock( + label="Číslo" + ), + ), + ( + "name", + wagtail.blocks.CharBlock( + label="Název" + ), + ), + ( + "points", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "content", + wagtail.blocks.TextBlock( + label="Obsah" + ), + ) + ] + ), + label="Body", + ), + ), + ] + ), + label="Kategorie", + ), + ), + ( + "long_version_url", + wagtail.blocks.URLBlock( + help_text="Pro zobrazení odkazu na celou verzi programu musí být obě následující pole vyplněná.", + label="Odkaz na celou verzi programu", + required=False, + ), + ), + ( + "long_version_text", + wagtail.blocks.CharBlock( + label="Nadpis odkazu na celou verzi programu", + required=False, + ), + ), + ] + ), + ), + ( + "news", + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + help_text="Nejnovější články se načtou automaticky", + label="Titulek", + ), + ), + ( + "description", + wagtail.blocks.TextBlock(label="Popis"), + ), + ], + template="styleguide2/includes/organisms/articles/elections/articles_section.html", + ), + ), + ], + blank=True, + use_json_field=True, + verbose_name="Hlavní obsah", + ), + ), + migrations.CreateModel( + name="ElectionsFullProgramPage", + 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.fields.StreamField( + [ + ("richtext", wagtail.blocks.RichTextBlock(label="Text")), + ( + "popout_block", + wagtail.blocks.StructBlock( + [ + ( + "categories", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "name", + wagtail.blocks.CharBlock( + label="Název" + ), + ), + ( + "icon", + wagtail.images.blocks.ImageChooserBlock( + label="Ikona", + required=False, + ), + ), + ( + "point_list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + label="Titulek vyskakovacího bloku" + ), + ), + ( + "content", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "h5", + "bold", + "italic", + "ol", + "ul", + "hr", + "link", + "document-link", + "image", + "superscript", + "subscript", + "strikethrough", + "blockquote", + "embed", + ], + label="Obsah", + ), + ), + ] + ), + label="Jednotlivé bloky programu", + ), + ), + ] + ), + label="Kategorie programu", + ), + ) + ] + ), + ), + ], + blank=True, + use_json_field=True, + verbose_name="Obsah", + ), + ), + ( + "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": "Celá verze programu", + }, + bases=( + shared.models.base.SubpageMixin, + wagtailmetadata.models.WagtailImageMetadataMixin, + "wagtailcore.page", + models.Model, + ), + ), + ] diff --git a/elections/models.py b/elections/models.py index 282e3d0294ac071919bc53e11c9f45d5f45c4aa6..8a0e4a6a9dcafafbf49b21cbc7e0550ce71512fa 100644 --- a/elections/models.py +++ b/elections/models.py @@ -85,6 +85,7 @@ class ElectionsHomePage(MainHomePageMixin): "elections.ElectionsCandidatesPage", "elections.ElectionsFaqPage", "elections.ElectionsSearchPage", + "elections.ElectionsFullProgramPage", ] ### OTHERS @@ -104,6 +105,10 @@ class ElectionsHomePage(MainHomePageMixin): def search_page_model(self): return ElectionsSearchPage + @property + def whole_program_page(self): + return self._first_subpage_of_type(ElectionsFullProgramPage) + @property def root_page(self): return self @@ -323,3 +328,35 @@ class ElectionsFaqPage( topic_names.append(section.value["topic"]) return topic_names + + +class ElectionsFullProgramPage( + ExtendedMetadataPageMixin, + SubpageMixin, + MetadataPageMixin, + PageInMenuMixin, + Page, +): + content = StreamField( + [ + ("richtext", RichTextBlock(label="Text")), + ("popout_block", shared_blocks.ProgramGroupBlockPopout()), + ], + verbose_name="Obsah", + blank=True, + use_json_field=True, + ) + + content_panels = Page.content_panels + [ + FieldPanel("content"), + ] + + promote_panels = make_promote_panels() + + ## RELATIONS + + parent_page_types = ["elections.ElectionsHomePage"] + subpage_types = [] + + class Meta: + verbose_name = "Celá verze programu" diff --git a/elections/templates/elections/elections_full_program_page.html b/elections/templates/elections/elections_full_program_page.html new file mode 100644 index 0000000000000000000000000000000000000000..7c2e4b31e68db75b2f4baf78554ab44955934e05 --- /dev/null +++ b/elections/templates/elections/elections_full_program_page.html @@ -0,0 +1,24 @@ +{% extends "styleguide2/article_page.html" %} + +{% load wagtailcore_tags %} + +{% block content %} + {% include 'styleguide2/includes/organisms/layout/elections/navbar.html' with selected_item=page.root_page.whole_program_page.get_menu_title %} + {% include 'styleguide2/includes/organisms/header/elections/simple_header.html' with title=page.title %} + + <main role="main" class="mb-10 xl:mb-32"> + <div class="container--wide flex flex-col"> + {% for block in page.content %} + {% if block.block_type == "popout_block" %} + {% include 'styleguide2/includes/organisms/popouts/popout_list.html' with categories=block.value.categories %} + {% elif block.block_type == "richtext" %} + <div class="prose max-w-screen-lg mb-4"> + {% include_block block %} + </div> + {% endif %} + {% endfor %} + </div> + </main> + + {% include 'styleguide2/includes/organisms/main_section/newsletter_section.html' %} +{% endblock %} diff --git a/main/blocks.py b/main/blocks.py index f5192156418d12b2ad46865236267f2deb98126e..adb791dab3b5668cdfe169e98bf140af22c71b88 100644 --- a/main/blocks.py +++ b/main/blocks.py @@ -11,26 +11,13 @@ from wagtail.blocks import ( ) from wagtail.images.blocks import ImageChooserBlock -from shared.blocks import CardLinkBlockMixin, CardLinkWithHeadlineBlockMixin, CTAMixin - -PROGRAM_RICH_TEXT_FEATURES = [ - "h3", - "h4", - "h5", - "bold", - "italic", - "ol", - "ul", - "hr", - "link", - "document-link", - "image", - "superscript", - "subscript", - "strikethrough", - "blockquote", - "embed", -] +from shared.blocks import ( + PROGRAM_RICH_TEXT_FEATURES, + CardLinkBlockMixin, + CardLinkWithHeadlineBlockMixin, + CTAMixin, +) +from shared.blocks import ProgramGroupBlockPopout as SharedProgramGroupBlockPopout class CardLinkBlock(CardLinkBlockMixin): @@ -184,29 +171,6 @@ class ProgramBlock(StructBlock): label = "Článek programu" -class ProgramBlockPopout(StructBlock): - title = CharBlock(label="Titulek vyskakovacího bloku") - content = RichTextBlock( - label="Obsah", - features=PROGRAM_RICH_TEXT_FEATURES, - ) - - class Meta: - icon = "date" - label = "Blok programu" - - -class ProgramPopoutCategory(StructBlock): - name = CharBlock(label="Název") - icon = ImageChooserBlock(label="Ikona", required=False) - - point_list = ListBlock(ProgramBlockPopout(), label="Jednotlivé bloky programu") - - class Meta: - icon = "date" - label = "Kategorie programu" - - class ProgramGroupBlock(ProgramGroupBlockMixin): point_list = ListBlock(ProgramBlock(), label="Jednotlivé články programu") @@ -223,14 +187,6 @@ class ProgramGroupBlockCrossroad(ProgramGroupBlockMixin): label = "Rozcestníkový program" -class ProgramGroupBlockPopout(ProgramGroupBlockMixin): - categories = ListBlock(ProgramPopoutCategory(), label="Kategorie programu") - - class Meta: - icon = "date" - label = "Vyskakovací program" - - class RegionsBlock(StructBlock): title = CharBlock( label="Titulek", @@ -354,6 +310,10 @@ class FlipCardsBlock(StructBlock): template = "styleguide2/includes/organisms/cards/flip_card_list.html" +class ProgramGroupBlockPopout(SharedProgramGroupBlockPopout): + pass + + # --- TODO: Remove legacy blocks used in migrations only diff --git a/main/migrations/0078_alter_mainprogrampage_program.py b/main/migrations/0078_alter_mainprogrampage_program.py new file mode 100644 index 0000000000000000000000000000000000000000..8d7f869800f464e649db52b4a241b15b1ceaab21 --- /dev/null +++ b/main/migrations/0078_alter_mainprogrampage_program.py @@ -0,0 +1,226 @@ +# Generated by Django 4.1.13 on 2024-03-12 14:54 + +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("main", "0077_alter_mainresultspage_content"), + ] + + operations = [ + migrations.AlterField( + model_name="mainprogrampage", + name="program", + field=wagtail.fields.StreamField( + [ + ( + "program_group", + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + label="Titulek části programu" + ), + ), + ( + "point_list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "url", + wagtail.blocks.URLBlock( + label="Odkaz pokrývající celou tuto část", + required=False, + ), + ), + ( + "icon", + wagtail.images.blocks.ImageChooserBlock( + label="Ikona", required=False + ), + ), + ( + "title", + wagtail.blocks.CharBlock( + label="Titulek článku programu" + ), + ), + ( + "text", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "h5", + "bold", + "italic", + "ol", + "ul", + "hr", + "link", + "document-link", + "image", + "superscript", + "subscript", + "strikethrough", + "blockquote", + "embed", + ], + label="Obsah", + ), + ), + ] + ), + label="Jednotlivé články programu", + ), + ), + ] + ), + ), + ( + "program_group_crossroad", + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + label="Titulek části programu" + ), + ), + ( + "point_list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + label="Obrázek" + ), + ), + ( + "title", + wagtail.blocks.CharBlock( + label="Titulek", required=True + ), + ), + ( + "text", + wagtail.blocks.RichTextBlock( + label="Krátký text pod nadpisem", + required=False, + ), + ), + ( + "page", + wagtail.blocks.PageChooserBlock( + label="Stránka", + page_type=[ + "main.MainArticlesPage", + "main.MainArticlePage", + "main.MainProgramPage", + "main.MainPeoplePage", + "main.MainPersonPage", + "main.MainSimplePage", + "main.MainContactPage", + "main.MainCrossroadPage", + ], + required=False, + ), + ), + ( + "link", + wagtail.blocks.URLBlock( + label="Odkaz", required=False + ), + ), + ] + ), + label="Karty programu", + ), + ), + ] + ), + ), + ( + "program_group_popout", + wagtail.blocks.StructBlock( + [ + ( + "categories", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "name", + wagtail.blocks.CharBlock( + label="Název" + ), + ), + ( + "icon", + wagtail.images.blocks.ImageChooserBlock( + label="Ikona", required=False + ), + ), + ( + "point_list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + label="Titulek vyskakovacího bloku" + ), + ), + ( + "content", + wagtail.blocks.RichTextBlock( + features=[ + "h3", + "h4", + "h5", + "bold", + "italic", + "ol", + "ul", + "hr", + "link", + "document-link", + "image", + "superscript", + "subscript", + "strikethrough", + "blockquote", + "embed", + ], + label="Obsah", + ), + ), + ] + ), + label="Jednotlivé bloky programu", + ), + ), + ] + ), + label="Kategorie programu", + ), + ) + ] + ), + ), + ], + blank=True, + use_json_field=True, + verbose_name="Program", + ), + ), + ] diff --git a/shared/blocks/main.py b/shared/blocks/main.py index 9dfe41cf9ce3ec4e3cff84c612d6c9817d58f38f..c2ebd6942a978fe02472b7ce348e0c926c8c4ca6 100644 --- a/shared/blocks/main.py +++ b/shared/blocks/main.py @@ -16,6 +16,26 @@ from .base import MenuItemBlock as MenuItemBlockBase # Mixins (or used as such) +PROGRAM_RICH_TEXT_FEATURES = [ + "h3", + "h4", + "h5", + "bold", + "italic", + "ol", + "ul", + "hr", + "link", + "document-link", + "image", + "superscript", + "subscript", + "strikethrough", + "blockquote", + "embed", +] + + class CTAMixin(StructBlock): button_link = URLBlock(label="Odkaz tlačítka") button_text = CharBlock(label="Text tlačítka") @@ -146,3 +166,34 @@ class OtherLinksBlock(StructBlock): icon = "link" label = "Odkazy" template = "main/blocks/article_quote_block.html" + + +class ProgramBlockPopout(StructBlock): + title = CharBlock(label="Titulek vyskakovacího bloku") + content = RichTextBlock( + label="Obsah", + features=PROGRAM_RICH_TEXT_FEATURES, + ) + + class Meta: + icon = "date" + label = "Blok programu" + + +class ProgramPopoutCategory(StructBlock): + name = CharBlock(label="Název") + icon = ImageChooserBlock(label="Ikona", required=False) + + point_list = ListBlock(ProgramBlockPopout(), label="Jednotlivé bloky programu") + + class Meta: + icon = "date" + label = "Kategorie programu" + + +class ProgramGroupBlockPopout(StructBlock): + categories = ListBlock(ProgramPopoutCategory(), label="Kategorie programu") + + class Meta: + icon = "date" + label = "Vyskakovací program"