diff --git a/district/blocks.py b/district/blocks.py index d99e658e1b0a6647a0cd8f0e4b585631e471c97e..d47a310c4e11b1411b2244143997b0cd3666db4b 100644 --- a/district/blocks.py +++ b/district/blocks.py @@ -1,4 +1,5 @@ from django.forms.utils import ErrorList +from django.utils.text import slugify from wagtail import blocks from wagtail.blocks import ( BooleanBlock, @@ -112,6 +113,81 @@ class NewsletterBlock(StructBlock): template = "styleguide2/includes/organisms/main_section/newsletter_section.html" +class PeopleGroupBlock(StructBlock): + title = CharBlock(label="Titulek") + slug = CharBlock( + label="Slug skupiny", + required=False, + help_text="Není třeba vyplňovat, bude automaticky vyplněno", + ) + person_list = ListBlock( + PageChooserBlock(page_type="district.DistrictPersonPage", label="Detail osoby"), + label="Skupina osob", + ) + + class Meta: + icon = "group" + label = "Slug skupiny" + + def get_prep_value(self, value): + value = super().get_prep_value(value) + value["slug"] = slugify(value["title"]) + return value + + +class CardLinkBlock(CardLinkBlockMixin): + page = PageChooserBlock( + label="Stránka", + page_type=[ + "district.DistrictHomepage", + ], + required=False, + ) + + class Meta: + template = "styleguide2/includes/molecules/boxes/card_box_block.html" + icon = "link" + label = "Karta s odkazem" + + +class CardLinkWithHeadlineBlock(CardLinkWithHeadlineBlockMixin): + card_items = ListBlock( + CardLinkBlock( + template="styleguide2/includes/molecules/boxes/card_box_block.html" + ), + label="Karty s odkazy", + ) + + class Meta: + template = ( + "styleguide2/includes/molecules/boxes/card_box_with_headline_block.html" + ) + icon = "link" + label = "Karty odkazů s nadpisem" + + +class TeamBlock(StructBlock): + title = CharBlock(label="Název sekce týmů") + slug = CharBlock( + label="Slug sekce", + required=False, + help_text="Není třeba vyplňovat, bude automaticky vyplněno", + ) + team_list = ListBlock( + CardLinkWithHeadlineBlock(label="Karta týmu"), + label="Týmy", + ) + + class Meta: + icon = "group" + label = "Týmy" + + def get_prep_value(self, value): + value = super().get_prep_value(value) + value["slug"] = slugify(value["title"]) + return value + + # --- END New blocks --- diff --git a/district/forms.py b/district/forms.py index 37b237fbdc4c91cc31408016870a9ca7a4c0f5a5..45b12efafb86376aa240cb2a98fcf530fa4e5405 100644 --- a/district/forms.py +++ b/district/forms.py @@ -1,42 +1,11 @@ import os -from django import forms - from shared.forms import JekyllImportForm as SharedJekyllImportForm from .tasks import import_jekyll_articles class JekyllImportForm(SharedJekyllImportForm): - use_git = forms.BooleanField( - initial=False, - required=False, - label="Použít Git", - help_text="Umožňuje jednodušší zpracování, ale vyžaduje nainstalovaný Git.", - ) - - def clean(self): - cleaned_data = super().clean() - - if not cleaned_data.get("do_import"): - return cleaned_data - - if cleaned_data.get("use_git"): - if cleaned_data.get("jekyll_repo_url", "").endswith(".zip"): - self.add_error( - "jekyll_repo_url", "Vložte odkaz pouze na repozitář, ne na zip" - ) - elif cleaned_data.get("jekyll_repo_url", "").endswith(".git"): - self.add_error( - "jekyll_repo_url", - "Vložte odkaz pouze na repozitář, ne na '.git' soubor", - ) - else: - if not cleaned_data.get("jekyll_repo_url", "").endswith(".zip"): - self.add_error("jekyll_repo_url", "Odkaz nesměřuje na soubor '.zip'") - - return cleaned_data - def handle_import(self): lock_file_name = f"/tmp/.{self.instance.id}.import-lock" diff --git a/district/migrations/0131_migrate_headers.py b/district/migrations/0131_migrate_headers.py index 27d3fadb9dfa720ca691bd949b8b648bd210dbce..359d42fceadbbc2cb00ac7af7e8be7b2600f7fac 100644 --- a/district/migrations/0131_migrate_headers.py +++ b/district/migrations/0131_migrate_headers.py @@ -33,6 +33,9 @@ def merge_blocks(apps, schema_editor): desktop_image = None mobile_image = None + button_url = None + button_text = None + # Titles if old_block["type"] in ( "header_full_size", @@ -105,8 +108,28 @@ def merge_blocks(apps, schema_editor): "button_text": button_text, } ) + merged_blocks.append(merged_block_data) + if len(merged_blocks) == 0: + merged_blocks = [ + FullscreenHeaderBlock().to_python( + { + "desktop_line_1": home_page.title, + "desktop_line_2": "", + "mobile_line_1": home_page.title, + "mobile_line_2": "", + "mobile_line_3": "", + "desktop_image": None, + "mobile_image": None, + "desktop_video_url": None, + "mobile_video_url": None, + "button_url": None, + "button_text": None, + } + ) + ] + for block in merged_blocks: home_page.content.append(("fullscreen_header_block", block)) diff --git a/district/migrations/0148_auto_20240510_1049.py b/district/migrations/0148_auto_20240510_1049.py index 33b964a543f5fd740d5747377ff0fb4494c648ef..d319278bf8b2c0ac1c71b9420f3dab376d6e170b 100644 --- a/district/migrations/0148_auto_20240510_1049.py +++ b/district/migrations/0148_auto_20240510_1049.py @@ -1,9 +1,9 @@ # Generated by Django 5.0.4 on 2024-05-10 08:49 -from django.db import migrations -from django.db import models -import wagtail import django +import wagtail +from django.db import migrations, models + from shared.blocks import NavbarMenuItemBlock @@ -54,11 +54,8 @@ def add_navbar_menu_items(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ - ('district', '0147_remove_districthomepage_contact_email_and_more'), + ("district", "0147_remove_districthomepage_contact_email_and_more"), ] - operations = [ - migrations.RunPython(add_navbar_menu_items) - ] + operations = [migrations.RunPython(add_navbar_menu_items)] diff --git a/district/migrations/0149_remove_districthomepage_contact_newcomers_and_more.py b/district/migrations/0149_remove_districthomepage_contact_newcomers_and_more.py index 329c3ba2af12a0798bed9d5cee2d75c41186581f..4f73c0f0f2e80e5bc4dbb7807697761265ef3e88 100644 --- a/district/migrations/0149_remove_districthomepage_contact_newcomers_and_more.py +++ b/district/migrations/0149_remove_districthomepage_contact_newcomers_and_more.py @@ -4,26 +4,25 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('district', '0148_auto_20240510_1049'), + ("district", "0148_auto_20240510_1049"), ] operations = [ migrations.RemoveField( - model_name='districthomepage', - name='contact_newcomers', + model_name="districthomepage", + name="contact_newcomers", ), migrations.RemoveField( - model_name='districthomepage', - name='donation_page', + model_name="districthomepage", + name="donation_page", ), migrations.RemoveField( - model_name='districthomepage', - name='show_eshop_link', + model_name="districthomepage", + name="show_eshop_link", ), migrations.RemoveField( - model_name='districthomepage', - name='show_magazine_link', + model_name="districthomepage", + name="show_magazine_link", ), ] diff --git a/district/migrations/0150_remove_districthomepage_footer_links_and_more.py b/district/migrations/0150_remove_districthomepage_footer_links_and_more.py index 827e2b4f04c6cc78ac383282c98ed74389864ad1..2de7b29983945e3e105ee299a38c211649d2aa6d 100644 --- a/district/migrations/0150_remove_districthomepage_footer_links_and_more.py +++ b/district/migrations/0150_remove_districthomepage_footer_links_and_more.py @@ -1,30 +1,52 @@ # Generated by Django 5.0.4 on 2024-05-10 10:33 -import shared.blocks.main import wagtail.blocks import wagtail.fields from django.db import migrations +import shared.blocks.main + class Migration(migrations.Migration): - dependencies = [ - ('district', '0149_remove_districthomepage_contact_newcomers_and_more'), + ("district", "0149_remove_districthomepage_contact_newcomers_and_more"), ] operations = [ migrations.RemoveField( - model_name='districthomepage', - name='footer_links', + model_name="districthomepage", + name="footer_links", ), migrations.AddField( - model_name='districthomepage', - name='footer_other_links', - field=wagtail.fields.StreamField([('other_links', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek')), ('list', wagtail.blocks.ListBlock(shared.blocks.main.LinkBlock, label='Seznam odkazů s titulkem'))]))], blank=True, verbose_name='Odkazy v zápatí webu'), + model_name="districthomepage", + name="footer_other_links", + field=wagtail.fields.StreamField( + [ + ( + "other_links", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(label="Titulek")), + ( + "list", + wagtail.blocks.ListBlock( + shared.blocks.main.LinkBlock, + label="Seznam odkazů s titulkem", + ), + ), + ] + ), + ) + ], + blank=True, + verbose_name="Odkazy v zápatí webu", + ), ), migrations.AlterField( - model_name='districthomepage', - name='footer_extra_content', - field=wagtail.fields.RichTextField(blank=True, verbose_name='Extra obsah na začátku patičky'), + model_name="districthomepage", + name="footer_extra_content", + field=wagtail.fields.RichTextField( + blank=True, verbose_name="Extra obsah na začátku patičky" + ), ), ] diff --git a/district/migrations/0151_alter_districthomepage_footer_other_links.py b/district/migrations/0151_alter_districthomepage_footer_other_links.py index 923671d5e21d49908a534ad468875cf8f7d64af9..e04c2365242673cb996e89c03416f146b10c79f6 100644 --- a/district/migrations/0151_alter_districthomepage_footer_other_links.py +++ b/district/migrations/0151_alter_districthomepage_footer_other_links.py @@ -1,21 +1,41 @@ # Generated by Django 5.0.4 on 2024-05-10 10:35 -import shared.blocks.main import wagtail.blocks import wagtail.fields from django.db import migrations +import shared.blocks.main + class Migration(migrations.Migration): - dependencies = [ - ('district', '0150_remove_districthomepage_footer_links_and_more'), + ("district", "0150_remove_districthomepage_footer_links_and_more"), ] operations = [ migrations.AlterField( - model_name='districthomepage', - name='footer_other_links', - field=wagtail.fields.StreamField([('other_links', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek')), ('list', wagtail.blocks.ListBlock(shared.blocks.main.LinkBlock, label='Seznam odkazů'))]))], blank=True, verbose_name='Odkazy v zápatí webu'), + model_name="districthomepage", + name="footer_other_links", + field=wagtail.fields.StreamField( + [ + ( + "other_links", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(label="Titulek")), + ( + "list", + wagtail.blocks.ListBlock( + shared.blocks.main.LinkBlock, + label="Seznam odkazů", + ), + ), + ] + ), + ) + ], + blank=True, + verbose_name="Odkazy v zápatí webu", + ), ), ] diff --git a/district/migrations/0152_auto_20240512_1336.py b/district/migrations/0152_auto_20240512_1336.py new file mode 100644 index 0000000000000000000000000000000000000000..996d6db89956be585ea07e234d92d91bd8ae76fb --- /dev/null +++ b/district/migrations/0152_auto_20240512_1336.py @@ -0,0 +1,25 @@ +# Generated by Django 5.0.4 on 2024-05-12 11:36 + +from django.db import migrations + + +def update_title_suffix(apps, schema_editor): + DistrictHomePage = apps.get_model("district", "DistrictHomePage") + + for home_page in DistrictHomePage.objects.all(): + if not home_page.title_suffix: + home_page.title_suffix = home_page.title + + home_page.title_suffix = home_page.title_suffix.replace("MS ", "").replace( + "KS ", "" + ) + + home_page.save() + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0151_alter_districthomepage_footer_other_links"), + ] + + operations = [migrations.RunPython(update_title_suffix)] diff --git a/district/migrations/0153_auto_20240512_1354.py b/district/migrations/0153_auto_20240512_1354.py new file mode 100644 index 0000000000000000000000000000000000000000..05193eaf437324d9d3726d5fac00a4141dfa6a18 --- /dev/null +++ b/district/migrations/0153_auto_20240512_1354.py @@ -0,0 +1,25 @@ +# Generated by Django 5.0.4 on 2024-05-12 11:54 + +from django.db import migrations + +from district.blocks import NewsletterBlock + + +def add_newsletter_blocks(apps, schema_editor): + DistrictHomePage = apps.get_model("district", "DistrictHomePage") + + for home_page in DistrictHomePage.objects.all(): + if not home_page.newsletter_list_id: + continue + + home_page.content.append(("newsletter_block", NewsletterBlock().to_python({}))) + + home_page.save() + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0152_auto_20240512_1336"), + ] + + operations = [migrations.RunPython(add_newsletter_blocks)] diff --git a/district/migrations/0154_alter_districtarticlespage_options_and_more.py b/district/migrations/0154_alter_districtarticlespage_options_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..5b042ae2ff550ff43766739b4b33c8d953b4a5dd --- /dev/null +++ b/district/migrations/0154_alter_districtarticlespage_options_and_more.py @@ -0,0 +1,26 @@ +# Generated by Django 5.0.4 on 2024-05-12 12:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0153_auto_20240512_1354"), + ] + + operations = [ + migrations.AlterModelOptions( + name="districtarticlespage", + options={"verbose_name": "Rozcestník článků"}, + ), + migrations.RemoveField( + model_name="districtarticlespage", + name="max_items", + ), + migrations.AddField( + model_name="districtarticlespage", + name="perex", + field=models.TextField(default=""), + preserve_default=False, + ), + ] diff --git a/district/migrations/0155_remove_districtarticlepage_is_black_and_more.py b/district/migrations/0155_remove_districtarticlepage_is_black_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..83c7dc4d3fb76da87346b684a67b03f85721774a --- /dev/null +++ b/district/migrations/0155_remove_districtarticlepage_is_black_and_more.py @@ -0,0 +1,69 @@ +# Generated by Django 5.0.4 on 2024-05-13 09:39 + +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0154_alter_districtarticlespage_options_and_more"), + ] + + operations = [ + migrations.RemoveField( + model_name="districtarticlepage", + name="is_black", + ), + migrations.AddField( + model_name="districtarticlepage", + name="show_initial_image", + field=models.BooleanField( + default=True, + help_text="Pokud je tato volba zaškrtnutá, obrázek nastavený u tohoto článku se automaticky vloží do prvního odstavce.", + verbose_name="Ukázat obrázek v textu", + ), + ), + migrations.AlterField( + model_name="districtarticlepage", + name="content", + field=wagtail.fields.StreamField( + [ + ( + "text", + wagtail.blocks.RichTextBlock( + template="styleguide2/includes/atoms/text/prose_richtext.html" + ), + ), + ( + "quote", + wagtail.blocks.StructBlock( + [ + ("quote", wagtail.blocks.CharBlock(label="Citace")), + ( + "autor_name", + wagtail.blocks.CharBlock(label="Jméno autora"), + ), + ] + ), + ), + ( + "download", + wagtail.blocks.StructBlock( + [ + ( + "file", + wagtail.documents.blocks.DocumentChooserBlock( + label="Stáhnutelný soubor" + ), + ) + ] + ), + ), + ], + blank=True, + verbose_name="Článek", + ), + ), + ] diff --git a/district/migrations/0156_alter_districtpeoplepage_options_and_more.py b/district/migrations/0156_alter_districtpeoplepage_options_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..8918e3ace8a694d90c3339e18bae3e5a91fb4b2e --- /dev/null +++ b/district/migrations/0156_alter_districtpeoplepage_options_and_more.py @@ -0,0 +1,153 @@ +# Generated by Django 5.0.4 on 2024-05-13 15:18 + +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0155_remove_districtarticlepage_is_black_and_more"), + ] + + operations = [ + migrations.AlterModelOptions( + name="districtpeoplepage", + options={"verbose_name": "Lidé a týmy"}, + ), + migrations.AddField( + model_name="districtpeoplepage", + name="people", + field=wagtail.fields.StreamField( + [ + ( + "people_group", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(label="Titulek")), + ( + "slug", + wagtail.blocks.CharBlock( + help_text="Není třeba vyplňovat, bude automaticky vyplněno", + label="Slug skupiny", + required=False, + ), + ), + ( + "person_list", + wagtail.blocks.ListBlock( + wagtail.blocks.PageChooserBlock( + label="Detail osoby", + page_type=["main.MainPersonPage"], + ), + label="Skupina osob", + ), + ), + ], + label="Seznam osob", + ), + ), + ( + "team_group", + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock(label="Název sekce týmů"), + ), + ( + "slug", + wagtail.blocks.CharBlock( + help_text="Není třeba vyplňovat, bude automaticky vyplněno", + label="Slug sekce", + required=False, + ), + ), + ( + "team_list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "headline", + wagtail.blocks.CharBlock( + label="Titulek bloku", + required=False, + ), + ), + ( + "card_items", + 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=[ + "district.DistrictHomePage" + ], + required=False, + ), + ), + ( + "link", + wagtail.blocks.URLBlock( + label="Odkaz", + required=False, + ), + ), + ], + template="styleguide2/includes/molecules/boxes/card_box_block.html", + ), + label="Karty s odkazy", + ), + ), + ], + label="Karta týmu", + ), + label="Týmy", + ), + ), + ] + ), + ), + ], + blank=True, + verbose_name="Lidé a týmy", + ), + ), + migrations.AddField( + model_name="districtpeoplepage", + name="perex_col_1", + field=models.TextField(default="", verbose_name="Perex - první sloupec"), + preserve_default=False, + ), + migrations.AddField( + model_name="districtpeoplepage", + name="perex_col_2", + field=models.TextField(default="", verbose_name="Perex - druhý sloupec"), + preserve_default=False, + ), + ] diff --git a/district/migrations/0158_rename_profile_photo_districtpersonpage_main_image.py b/district/migrations/0158_rename_profile_photo_districtpersonpage_main_image.py new file mode 100644 index 0000000000000000000000000000000000000000..edbb6a7e41f8eaa1d47707db4c64b1ceecb7aee3 --- /dev/null +++ b/district/migrations/0158_rename_profile_photo_districtpersonpage_main_image.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.4 on 2024-05-13 16:48 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0156_alter_districtpeoplepage_options_and_more"), + ] + + operations = [ + migrations.RenameField( + model_name="districtpersonpage", + old_name="profile_photo", + new_name="main_image", + ), + ] diff --git a/district/migrations/0159_rename_main_image_districtpersonpage_profile_image.py b/district/migrations/0159_rename_main_image_districtpersonpage_profile_image.py new file mode 100644 index 0000000000000000000000000000000000000000..7285ea756328ea9387b599628174fbaa935bd376 --- /dev/null +++ b/district/migrations/0159_rename_main_image_districtpersonpage_profile_image.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.4 on 2024-05-13 16:52 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0158_rename_profile_photo_districtpersonpage_main_image"), + ] + + operations = [ + migrations.RenameField( + model_name="districtpersonpage", + old_name="main_image", + new_name="profile_image", + ), + ] diff --git a/district/migrations/0160_rename_background_photo_districtpersonpage_main_image.py b/district/migrations/0160_rename_background_photo_districtpersonpage_main_image.py new file mode 100644 index 0000000000000000000000000000000000000000..ff07f5ed665833833b3a98a33e57452afc1d3a2f --- /dev/null +++ b/district/migrations/0160_rename_background_photo_districtpersonpage_main_image.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.4 on 2024-05-13 16:52 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0159_rename_main_image_districtpersonpage_profile_image"), + ] + + operations = [ + migrations.RenameField( + model_name="districtpersonpage", + old_name="background_photo", + new_name="main_image", + ), + ] diff --git a/district/migrations/0161_auto_20240513_1733.py b/district/migrations/0161_auto_20240513_1733.py new file mode 100644 index 0000000000000000000000000000000000000000..363271e20e21407b558d9a66d9e724c0801539db --- /dev/null +++ b/district/migrations/0161_auto_20240513_1733.py @@ -0,0 +1,191 @@ +# Generated by Django 5.0.4 on 2024-05-13 15:33 + +import wagtail +from django.db import migrations +from wagtail.blocks import PageChooserBlock + +from district.blocks import PeopleGroupBlock + + +def migrate_people_blocks(apps, schema_editor): + # Get the page model + DistrictPeoplePage = apps.get_model("district", "DistrictPeoplePage") + DistrictPersonPage = apps.get_model("district", "DistrictPersonPage") + + # Iterate over all pages that have the StreamField you want to update + for number, people_page in enumerate(DistrictPeoplePage.objects.all()): + # Get the old content + old_content = people_page.content.get_prep_value() + + # Create a new list to store the merged blocks + merged_blocks = [] + + # Iterate over the old blocks and extract common fields + for old_block in old_content: + if old_block["type"] != "people_group": + continue + + title = old_block["value"]["group_title"] + people = [] + + for person in old_block["value"]["person_list"]: + person_id = DistrictPersonPage.objects.filter( + id=person["value"]["person"] + ).values_list("id", flat=True).first() + + if person_id is None: + continue + + people.append(person_id) + + person_block_list = [] + + for person_id in people: + person_block_list.append(person_id) + + merged_blocks.append( + PeopleGroupBlock().to_python( + { + "title": title, + "slug": str(number), + "person_list": person_block_list, + } + ) + ) + + for block in merged_blocks: + people_page.people.append(("people_group", block)) + + people_page.save() + + +class Migration(migrations.Migration): + dependencies = [ + ("district", "0160_rename_background_photo_districtpersonpage_main_image"), + ] + + operations = [ + migrations.AlterField( + model_name="districtpeoplepage", + name="people", + field=wagtail.fields.StreamField( + [ + ( + "people_group", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(label="Titulek")), + ( + "slug", + wagtail.blocks.CharBlock( + help_text="Není třeba vyplňovat, bude automaticky vyplněno", + label="Slug skupiny", + required=False, + ), + ), + ( + "person_list", + wagtail.blocks.ListBlock( + wagtail.blocks.PageChooserBlock( + label="Detail osoby", + page_type=["district.DistrictPersonPage"], + ), + label="Skupina osob", + ), + ), + ], + label="Seznam osob", + ), + ), + ( + "team_group", + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock(label="Název sekce týmů"), + ), + ( + "slug", + wagtail.blocks.CharBlock( + help_text="Není třeba vyplňovat, bude automaticky vyplněno", + label="Slug sekce", + required=False, + ), + ), + ( + "team_list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "headline", + wagtail.blocks.CharBlock( + label="Titulek bloku", + required=False, + ), + ), + ( + "card_items", + 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=[ + "district.DistrictHomePage" + ], + required=False, + ), + ), + ( + "link", + wagtail.blocks.URLBlock( + label="Odkaz", + required=False, + ), + ), + ], + template="styleguide2/includes/molecules/boxes/card_box_block.html", + ), + label="Karty s odkazy", + ), + ), + ], + label="Karta týmu", + ), + label="Týmy", + ), + ), + ] + ), + ), + ], + blank=True, + verbose_name="Lidé a týmy", + ), + ), + migrations.RunPython(migrate_people_blocks), + ] diff --git a/district/models.py b/district/models.py index 89b98ebeb15ba3d3af7c4e0565a8022db4759568..b1cb65ef25fceedb2fd52ada29090ef7ccd71ff7 100644 --- a/district/models.py +++ b/district/models.py @@ -56,8 +56,11 @@ from shared.models import ( ExtendedMetadataHomePageMixin, ExtendedMetadataPageMixin, FooterMixin, + MainArticlePageMixin, + MainArticlesPageMixin, MainFooterMixin, MainMenuMixin, + MainPeoplePageMixin, MenuMixin, PdfPageMixin, SharedTaggedDistrictArticle, @@ -306,9 +309,17 @@ class DistrictHomePage( )[:6] ) + @property + def articles_page_model(self): + return DistrictArticlesPage + + @property + def article_page_model(self): + return DistrictArticlePage + @property def articles_page(self): - return self._first_subpage_of_type(DistrictArticlesPage) + return self._first_subpage_of_type(self.articles_page_model) @property def center_page(self): @@ -364,15 +375,12 @@ class DistrictArticleTag(TaggedItemBase): ) -class DistrictArticlePage( - ArticleMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page -): +class DistrictArticlePage(MainArticlePageMixin): ### FIELDS author_page = models.ForeignKey( "district.DistrictPersonPage", on_delete=models.SET_NULL, null=True, blank=True ) - is_black = models.BooleanField("Má tmavé pozadí?", default=False) tags = ClusterTaggableManager(through=DistrictArticleTag, blank=True) shared_tags = ClusterTaggableManager( verbose_name="Tagy pro sdílení mezi weby", @@ -388,216 +396,20 @@ class DistrictArticlePage( related_name="thumb_image", ) - search_fields = ArticleMixin.search_fields + [ - index.SearchField("author_page"), - index.FilterField("slug"), - ] - - ### PANELS - - content_panels = ArticleMixin.content_panels + [ - FieldPanel("author_page"), - FieldPanel("is_black"), - FieldPanel("tags"), - FieldPanel("shared_tags"), - FieldPanel("thumb_image"), - ] - - promote_panels = make_promote_panels( - admin_help.build(admin_help.NO_SEO_TITLE, admin_help.NO_DESCRIPTION_USE_PEREX), - search_image=False, - ) - ### RELATIONS parent_page_types = ["district.DistrictArticlesPage"] subpage_types = ["district.DistrictPdfPage"] - ### OTHERS - - class Meta: - verbose_name = "Aktualita" - - def clean(self): - cleaned_data = super().clean() - - if not self.image and not self.thumb_image: - raise ValidationError("Musí být nahraný buď obrázek nebo náhledový obrázek") - - return cleaned_data - - def get_context(self, request): - context = super().get_context(request) - context["related_articles"] = ( - ( - self.get_siblings(inclusive=False) - .live() # TODO? filtrovat na stejné tagy? nebo sdílené články? - .specific() - .order_by("-districtarticlepage__timestamp")[:3] - ) - if self.shared_from is None - else [] - ) - return context +class DistrictArticlesPage(MainArticlesPageMixin): + base_form_class = JekyllImportForm -class DistrictArticlesPage( - RoutablePageMixin, - ExtendedMetadataPageMixin, - SubpageMixin, - MetadataPageMixin, - ArticlesPageMixin, - Page, -): ### FIELDS - last_import_log = models.TextField( - "Výstup z posledního importu", null=True, blank=True - ) - max_items = models.IntegerField("Počet článků na stránce", default=12) - - ### PANELS - - content_panels = ArticlesPageMixin.content_panels + [ - FieldPanel("max_items"), - ] - - promote_panels = make_promote_panels() - - import_panels = [ - MultiFieldPanel( - [ - FieldPanel("do_import"), - FieldPanel("collection"), - FieldPanel("dry_run"), - FieldPanel("use_git"), - FieldPanel("jekyll_repo_url"), - FieldPanel("readonly_log"), - HelpPanel( - mark_safe( - "Import provádějte vždy až po vytvoření stránky aktualit. " - "Pro uložení logu je nutné volit možnost <strong>Publikovat</strong>, nikoliv " - "pouze <strong>Uložit koncept</strong>. " - "Import proběhne na pozadí a může trvat až několik minut. " - "Dejte si po spuštění importu kávu a potom obnovte stránku pro " - "zobrazení výsledku importu." - ) - ), - ], - "import z Jekyll repozitáře", - ), - ] - - ### EDIT HANDLERS - - edit_handler = TabbedInterface( - [ - ObjectList(content_panels, heading="Obsah"), - ObjectList(promote_panels, heading="Propagovat"), - ObjectList(import_panels, heading="Import"), - ] - ) - - ### RELATIONS - parent_page_types = ["district.DistrictHomePage"] subpage_types = ["district.DistrictArticlePage"] - ### OTHERS - - base_form_class = JekyllImportForm - - class Meta: - verbose_name = "Aktuality" - - def get_context(self, request): - context = super().get_context(request) - context["articles"] = self.get_page_with_shared_articles( - self.append_all_shared_articles_query( - DistrictArticlePage.objects.child_of(self) - ), - self.max_items, - request.GET.get("page", 1), - ) - return context - - @route(r"^tagy/$", name="tags") - def tags(self, request): - return render( - request, - "district/district_tags_page.html", - context=self.get_tags_page_context(request=request), - ) - - @route(r"^sdilene/$", name="shared") - def shared(self, request): - return self.setup_article_page_context(request) - - def get_tags_page_context(self, request) -> dict: - # 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) - context = super().get_context(request) - - articles = self.materialize_articles_as_id_only( - self.append_all_shared_articles_query( - DistrictArticlePage.objects.child_of(self) - ) - ) - - page_ids = list(map(lambda article: article.page_ptr.id, articles)) - - # Naplním "tag" a "article_page_list" parametry - context.update(**self.get_tag_and_articles(request, page_ids)) - context["tag_list"] = self.get_tag_qs(articles) - - # 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, page_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 = None - tag = None - - try: - tag = Tag.objects.filter(slug=request.GET["tag"])[0] - article_page_qs = self.append_all_shared_articles_query( - DistrictArticlePage.objects.filter( - page_ptr_id__in=page_ids, tags__slug=tag.slug - ), - custom_article_query=lambda shared: shared.filter( - page_ptr_id__in=page_ids, tags__slug=tag.slug - ), - ) - except (KeyError, IndexError): - tag = None - article_page_qs = self.append_all_shared_articles_query( - DistrictArticlePage.objects.filter(page_ptr_id__in=page_ids), - custom_article_query=lambda shared: shared.filter( - page_ptr_id__in=page_ids - ), - ) - - return { - "article_page_list": self.get_page_with_shared_articles( - article_page_qs, self.max_items, request.GET.get("page", 1) - ), - "tag": tag, - } - - def get_tag_qs(self, articles: 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 self.search_tags_with_count(articles) - class DistrictContactPage( ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page @@ -660,7 +472,7 @@ class DistrictPersonPage( job_function = models.CharField( "Funkce", max_length=128, blank=True, null=True, help_text="Např. 'Předseda'" ) - background_photo = models.ForeignKey( + main_image = models.ForeignKey( "wagtailimages.Image", on_delete=models.PROTECT, blank=True, @@ -668,7 +480,7 @@ class DistrictPersonPage( related_name="+", verbose_name="obrázek do záhlaví", ) - profile_photo = models.ForeignKey( + profile_image = models.ForeignKey( "wagtailimages.Image", on_delete=models.PROTECT, blank=True, @@ -726,8 +538,8 @@ class DistrictPersonPage( ), MultiFieldPanel( [ - FieldPanel("profile_photo"), - FieldPanel("background_photo"), + FieldPanel("profile_image"), + FieldPanel("main_image"), ], "Fotky", ), @@ -807,11 +619,7 @@ class DistrictPersonPage( return None -class DistrictPeoplePage( - ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page -): - ### FIELDS - +class DistrictPeoplePage(MainPeoplePageMixin): content = StreamField( [ ( @@ -827,24 +635,26 @@ class DistrictPeoplePage( use_json_field=True, ) - ### PANELS - - content_panels = Page.content_panels + [FieldPanel("content")] - - promote_panels = make_promote_panels() - - settings_panels = [] + people = StreamField( + [ + ("people_group", blocks.PeopleGroupBlock(label="Seznam osob")), + ("team_group", blocks.TeamBlock()), + ], + verbose_name="Lidé a týmy", + blank=True, + use_json_field=True, + ) - ### RELATIONS + content_panels = Page.content_panels + [ + FieldPanel("perex_col_1"), + FieldPanel("perex_col_2"), + FieldPanel("people"), + FieldPanel("content"), + ] parent_page_types = ["district.DistrictHomePage"] subpage_types = ["district.DistrictPersonPage"] - ### OTHERS - - class Meta: - verbose_name = "Lidé" - class DistrictElectionBasePage( ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page diff --git a/district/templates/district/district_article_page.html b/district/templates/district/district_article_page.html index d3fda22bda7269e44d38a73e9aa593aec3850a5a..c43dc3736130fcb86ae32958c9c7604117a56949 100644 --- a/district/templates/district/district_article_page.html +++ b/district/templates/district/district_article_page.html @@ -1,99 +1 @@ -{% extends "district/base.html" %} -{% load static wagtailcore_tags wagtailimages_tags wagtailroutablepage_tags %} - -{% block content %} - {% if page.root_page.articles_page %} - {% routablepageurl page.root_page.articles_page "tags" as articles_tag_page_url %} - {% endif %} - - <article> - <link itemprop="mainEntityOfPage" href="{{ page.url }}"> - <meta itemprop="datePublished" content="{{ page.last_published_at }}"> - <meta itemprop="dateModified" content="{{ page.latest_revision_created_at }}"> - - <h1 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:"DATE_FORMAT" }}</span> - <span class="pl-2" itemprop="author" itemtype="http://schema.org/Person" itemscope=""> - {% if page.author_page %} - <a href="{{ page.author_page.url }}" itemprop="name">{{ page.author }}</a> - {% else %} - <span itemprop="name">{{ page.author|default_if_none:'' }}</span> - {% endif %} - </span> - </div> - <div class="my-4"> - {% for tag in page.get_tags %} - <a href="{{ articles_tag_page_url }}?tag={{ tag.slug }}" class="btn btn--grey-125 btn--condensed"> - <div class="btn__body ">{{ tag }}</div> - </a> - {% endfor %} - </div> - </div> - {% if page.image %} - <figure class="figure"> - {% image page.image width-2000 as img %} - <img src="{{ img.url }}" alt="{{ page.title }}"/> - </figure> - {% endif %} - <div class="lg:flex mt-8 lg:space-x-16"> - <div class="lg:w-2/3"> - <div itemprop="description" class="w-full space-y-8"> - {% for block in page.content %} - {% include_block block %} - {% endfor %} - - {% if page.author_page %} - {% include "shared/person_badge_snippet.html" with person_page=page.author_page title="Autor" %} - {% endif %} - </div> - - </div> - <div class="pt-8 lg:w-1/3 md:pt-0"> - <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> - - {% include "shared/article_shared_link.html" %} - </article> - - {% if related_articles|length %} - <section class="mt-16 md:mt-24"> - <h1 class="head-alt-base md:head-alt-md pb-4"> - Další podobné články - </h1> - - <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8"> - {% for article in related_articles %} - {% include "shared/article_preview.html" %} - {% endfor %} - </div> - - {% include "shared/more_articles_snippet.html" %} - </section> - {% endif %} - -{% endblock %} +{% extends "styleguide2/article_page.html" %} diff --git a/district/templates/district/district_people_page.html b/district/templates/district/district_people_page.html index c42a4644f91d3ac2938929ad7b19615005d8f7eb..ea5b544757f07fdadac7302fb92f2e20ddb48272 100644 --- a/district/templates/district/district_people_page.html +++ b/district/templates/district/district_people_page.html @@ -1,17 +1 @@ -{% extends "district/base.html" %} -{% load wagtailcore_tags wagtailimages_tags shared_filters %} - -{% block content %} - <header> - <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8"> - {{ page.title }} - </h1> - </header> - - {% for block in page.content %} - {% include_block block %} - {% if not forloop.last %} - <hr class="hr--big"> - {% endif %} - {% endfor %} -{% endblock %} +{% extends "styleguide2/people_page.html" %} diff --git a/elections/migrations/0028_alter_electionshomepage_footer_other_links.py b/elections/migrations/0028_alter_electionshomepage_footer_other_links.py index a830c0ff9a2a29669c06507efd0784b857ce0b77..b0f25d605091489be2d91bf4417a1e5c0cc35928 100644 --- a/elections/migrations/0028_alter_electionshomepage_footer_other_links.py +++ b/elections/migrations/0028_alter_electionshomepage_footer_other_links.py @@ -1,21 +1,41 @@ # Generated by Django 5.0.4 on 2024-05-10 10:35 -import shared.blocks.main import wagtail.blocks import wagtail.fields from django.db import migrations +import shared.blocks.main + class Migration(migrations.Migration): - dependencies = [ - ('elections', '0027_alter_electionshomepage_content'), + ("elections", "0027_alter_electionshomepage_content"), ] operations = [ migrations.AlterField( - model_name='electionshomepage', - name='footer_other_links', - field=wagtail.fields.StreamField([('other_links', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek')), ('list', wagtail.blocks.ListBlock(shared.blocks.main.LinkBlock, label='Seznam odkazů'))]))], blank=True, verbose_name='Odkazy v zápatí webu'), + model_name="electionshomepage", + name="footer_other_links", + field=wagtail.fields.StreamField( + [ + ( + "other_links", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(label="Titulek")), + ( + "list", + wagtail.blocks.ListBlock( + shared.blocks.main.LinkBlock, + label="Seznam odkazů", + ), + ), + ] + ), + ) + ], + blank=True, + verbose_name="Odkazy v zápatí webu", + ), ), ] diff --git a/main/migrations/0083_alter_mainhomepage_footer_other_links.py b/main/migrations/0083_alter_mainhomepage_footer_other_links.py index d02adaf239f546a6eb73722803e0bcee3ca749be..5112a6db62652f4fb9743cb7144fe26f632ac820 100644 --- a/main/migrations/0083_alter_mainhomepage_footer_other_links.py +++ b/main/migrations/0083_alter_mainhomepage_footer_other_links.py @@ -1,21 +1,41 @@ # Generated by Django 5.0.4 on 2024-05-10 10:35 -import shared.blocks.main import wagtail.blocks import wagtail.fields from django.db import migrations +import shared.blocks.main + class Migration(migrations.Migration): - dependencies = [ - ('main', '0082_alter_mainhomepage_content'), + ("main", "0082_alter_mainhomepage_content"), ] operations = [ migrations.AlterField( - model_name='mainhomepage', - name='footer_other_links', - field=wagtail.fields.StreamField([('other_links', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek')), ('list', wagtail.blocks.ListBlock(shared.blocks.main.LinkBlock, label='Seznam odkazů'))]))], blank=True, verbose_name='Odkazy v zápatí webu'), + model_name="mainhomepage", + name="footer_other_links", + field=wagtail.fields.StreamField( + [ + ( + "other_links", + wagtail.blocks.StructBlock( + [ + ("title", wagtail.blocks.CharBlock(label="Titulek")), + ( + "list", + wagtail.blocks.ListBlock( + shared.blocks.main.LinkBlock, + label="Seznam odkazů", + ), + ), + ] + ), + ) + ], + blank=True, + verbose_name="Odkazy v zápatí webu", + ), ), ] diff --git a/main/models.py b/main/models.py index aacfb08d88e2e8968594b4e75a5ddd985d1535a4..728c9e676c515c4310cf71dd62cbc050e304c373 100644 --- a/main/models.py +++ b/main/models.py @@ -38,6 +38,7 @@ from shared.models import ( # MenuMixin, MainArticlesPageMixin, MainContactPageMixin, MainHomePageMixin, + MainPeoplePageMixin, MainSearchPageMixin, MainSimplePageMixin, PageInMenuMixin, @@ -205,18 +206,7 @@ class MainProgramPage( verbose_name = "Program" -class MainPeoplePage( - ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page -): - ### FIELDS - - perex_col_1 = models.TextField( - verbose_name="Perex - první sloupec", - ) - perex_col_2 = models.TextField( - verbose_name="Perex - druhý sloupec", - ) - +class MainPeoplePage(MainPeoplePageMixin): people = StreamField( [ ("people_group", blocks.PeopleGroupBlock(label="Seznam osob")), @@ -227,35 +217,6 @@ class MainPeoplePage( use_json_field=True, ) - ### PANELS - - content_panels = Page.content_panels + [ - FieldPanel("perex_col_1"), - FieldPanel("perex_col_2"), - FieldPanel("people"), - ] - - promote_panels = make_promote_panels() - - settings_panels = [] - - ### RELATIONS - - parent_page_types = ["main.MainHomePage"] - subpage_types = [ - "main.MainPersonPage", - "main.MainSimplePage", - ] - - ### OTHERS - - @property - def perex(self) -> str: - return self.perex_col_1 + " \n" + self.perex_col_2 - - class Meta: - verbose_name = "Lidé a týmy" - class MainPersonPage( ExtendedMetadataPageMixin, diff --git a/main/templates/main/main_people_page.html b/main/templates/main/main_people_page.html index a407a5c3596c37a27d5c7e39d9968394ae141f1c..ea5b544757f07fdadac7302fb92f2e20ddb48272 100644 --- a/main/templates/main/main_people_page.html +++ b/main/templates/main/main_people_page.html @@ -1,66 +1 @@ -{% extends "styleguide2/base.html" %} -{% load wagtailcore_tags wagtailimages_tags shared_filters %} - -{% block content %} -{% include 'styleguide2/includes/organisms/layout/navbar.html' with selected_item=page.get_menu_title %} - -<div class="__js-root"> - <ui-view-provider - :initial="{ {% for people_group in page.people %}'{{ people_group.value.slug }}-{{ forloop.counter }}': {% if forloop.counter0 %}false{% else %}true{% endif %},{% endfor %} }" - :sync-location="true" - v-slot="{ isCurrentView, toggleView }" - > - {% include 'styleguide2/includes/organisms/header/people_header.html' with people=page.people title=page.title description_column_1=page.perex_col_1 description_column_2=page.perex_col_2 %} - - <main role="main" class="mb-20"> - <div class="container--wide"> - <div - class=" - flex flex-wrap justify-center gap-4 - xl:justify-start - " - > - <div class="grid grid-cols-1 gap-4 md:grid-cols-2 w-full"> - {% for block in page.people %} - {% if block.block_type == "people_group" %} - <template v-if="isCurrentView('{{ block.value.slug }}-{{ forloop.counter }}')"> - {% for person_page in block.value.person_list %} - {% image person_page.profile_image fill-480x480 as profile_image %} - - {% include 'styleguide2/includes/molecules/contact/contact_person_large_box.html' with image=profile_image name=person_page.title function=person_page.position telephone=person_page.phone mail=person_page.email url=person_page.url %} - {% endfor %} - </template> - {% endif %} - {% endfor %} - </div> - - {% for block in page.people %} - {% if block.block_type == "team_group" %} - <template v-if="isCurrentView('{{ block.value.slug }}-{{ forloop.counter }}')"> - {% for team in block.value.team_list %} - - {% if team.headline %} - <h2 class="head-6xl mt-5 mb-5">{{ team.headline }}</h2> - {% endif %} - - <ul class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 content-stretch gap-8"> - {% for card in team.card_items %} - {% image card.image max-512x512 as card_image %} - {% firstof card.page.url card.link as card_url %} - - {% include 'styleguide2/includes/molecules/boxes/card_box.html' with image=card_image header=card.title content=card.text url=card_url description_classes='!bg-grey-180' %} - {% endfor %} - </ul> - {% endfor %} - </template> - {% endif %} - {% endfor %} - </div> - </div> - </main> - </ui-view-provider> -</div> - -{% include 'styleguide2/includes/organisms/main_section/newsletter_section.html' %} - -{% endblock content %} +{% extends "styleguide2/people_page.html" %} diff --git a/shared/migrations/0005_auto_20240513_0955.py b/shared/migrations/0005_auto_20240513_0955.py new file mode 100644 index 0000000000000000000000000000000000000000..1daa62f5d75157845e2237f83dd6e0dd249b2ff7 --- /dev/null +++ b/shared/migrations/0005_auto_20240513_0955.py @@ -0,0 +1,35 @@ +# Generated by Django 5.0.4 on 2024-05-13 07:55 + +from django.db import migrations + + +def fix_tags_names(apps, schema_editor): + Tag = apps.get_model("taggit", "Tag") + + for tag in Tag.objects.all(): + tag.name = tag.name.replace("-", " ") + tag.name = tag.name.replace("_", " ") + + if not tag.name[0].isupper(): + tag.name = tag.name[0].upper() + tag.name[1:] + + if Tag.objects.filter(name=tag.name).exists(): + # Workaround + tag.name += " " + + if Tag.objects.filter(name=tag.name).exists(): + tag.name += " " + + if Tag.objects.filter(name=tag.name).exists(): + print(f"Tag {tag.name} already exists.") + continue + + tag.save() + + +class Migration(migrations.Migration): + dependencies = [ + ("shared", "0004_sharedtaggedelectionsarticle"), + ] + + operations = [migrations.RunPython(fix_tags_names)] diff --git a/shared/models/main.py b/shared/models/main.py index aee43fff435a1dd9dc20e86d564edff9fede0ecd..700768ab0f6ba755a7811bbdd97c0b81228b3159 100644 --- a/shared/models/main.py +++ b/shared/models/main.py @@ -55,6 +55,8 @@ from .base import ( # MenuMixin, from .base import MenuMixin as MenuMixinBase from .base import SharedTaggedMainArticle, SubpageMixin # MenuMixin, +# MenuMixin, + class MainFooterMixin(Page): footer_other_links = StreamField( @@ -515,25 +517,40 @@ class MainArticlesPageMixin( search_filter = self.get_search_filters(request) - articles = self.get_base_shared_articles_query(search_filter)[:self.ARTICLE_LIST_COUNT + 1] + articles = self.get_base_shared_articles_query(search_filter)[ + : self.ARTICLE_LIST_COUNT + 1 + ] more_articles_exist = len(articles) > self.ARTICLE_LIST_COUNT - articles = articles[:self.ARTICLE_LIST_COUNT] + articles = articles[: self.ARTICLE_LIST_COUNT] ctx["articles"] = articles ctx["show_next_timeline_articles"] = more_articles_exist ctx["article_count"] = len(articles) tags = [] + tag_count = {} - for article in self.root_page.article_page_model.objects.all()[:50]: + for article in self.root_page.article_page_model.objects.child_of( + self + ).all()[:150]: for tag in article.tags.all(): + if tag not in tags: + tag_count[tag] = 1 + if tag in tags: + tag_count[tag] += 1 + continue tags.append(tag) + tags.sort(key=lambda tag: tag_count[tag], reverse=True) + + # Limit to a maximum of 30 tags + tags = tags[:30] + ctx["tags"] = tags # meow @@ -550,7 +567,9 @@ class MainArticlesPageMixin( else: article_count = self.ARTICLE_LIST_COUNT - articles = self.get_base_shared_articles_query(search_filter)[:article_count + 1] + articles = self.get_base_shared_articles_query(search_filter)[ + : article_count + 1 + ] more_articles_exist = len(articles) > article_count @@ -790,3 +809,46 @@ class MainSimplePageMixin( class Meta: verbose_name = "Jednoduchá stárnka" abstract = True + + +class MainPeoplePageMixin( + ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page +): + ### FIELDS + + perex_col_1 = models.TextField( + verbose_name="Perex - první sloupec", + ) + perex_col_2 = models.TextField( + verbose_name="Perex - druhý sloupec", + ) + + ### PANELS + + content_panels = Page.content_panels + [ + FieldPanel("perex_col_1"), + FieldPanel("perex_col_2"), + FieldPanel("people"), + ] + + promote_panels = make_promote_panels() + + settings_panels = [] + + ### RELATIONS + + parent_page_types = ["main.MainHomePage"] + subpage_types = [ + "main.MainPersonPage", + "main.MainSimplePage", + ] + + ### OTHERS + + @property + def perex(self) -> str: + return self.perex_col_1 + " \n" + self.perex_col_2 + + class Meta: + verbose_name = "Lidé a týmy" + abstract = True diff --git a/shared/templates/styleguide2/article_page.html b/shared/templates/styleguide2/article_page.html index 65658ca7ec10eb8df189fab405d906dad7670df8..d00e3232aefd39478dfb7c39e4a0b9d5bd4e187f 100644 --- a/shared/templates/styleguide2/article_page.html +++ b/shared/templates/styleguide2/article_page.html @@ -4,7 +4,7 @@ {% block content %} {% include 'styleguide2/includes/organisms/layout/navbar.html' with selected_item=page.root_page.articles_page.get_menu_title %} -{% include 'styleguide2/includes/organisms/header/article_header.html' with title=page.title description=page.perex tags=page.tags.names first_nav_text=page.root_page.articles_page.title first_nav_link=page.root_page.articles_page.url second_nav_text=page.date %} +{% include 'styleguide2/includes/organisms/header/article_header.html' with title=page.title description=page.perex tags=page.tags.all first_nav_text=page.root_page.articles_page.title first_nav_link=page.root_page.articles_page.url second_nav_text=page.date %} <main role="main" class="mb-10 xl:mb-32"> <div class="container--wide flex flex-col"> diff --git a/shared/templates/styleguide2/includes/atoms/tags/tag.html b/shared/templates/styleguide2/includes/atoms/tags/tag.html index 93c57a0a8c4ffb6f8faf50325eed9af46589f558..050743612299ee4ba013d58b977cc17791765eb9 100644 --- a/shared/templates/styleguide2/includes/atoms/tags/tag.html +++ b/shared/templates/styleguide2/includes/atoms/tags/tag.html @@ -1,20 +1,28 @@ -<a - href="{% if tags_are_selectable %}?tag_id={{ id }}{% endif %}" - class=" - {% if color_classes %} - {{ color_classes }} - {% else %} - text-black bg-yellow-500 hover:bg-yellow-600 - {% endif %} +{% if tags_are_selectable %} + <a + href="?tag_id={{ id }}" +{% else %} + <span +{% endif %} + class=" + {% if color_classes %} + {{ color_classes }} + {% else %} + text-black bg-yellow-500 {% if tags_are_selectable %}hover:bg-yellow-600{% endif %} + {% endif %} - px-4 py-2 duration-200 hover:no-underline - " - style=" - {% if filtered_tag and filtered_tag.id == id %} - background:white !important; - color:black !important; - {% endif %} - " -> - {{ text }} -</a> + px-4 py-2 duration-200 hover:no-underline + " + style=" + {% if filtered_tag and filtered_tag.id == id %} + background:white !important; + color:black !important; + {% endif %} + " + > + {{ text }} +{% if tags_are_selectable %} + </a> +{% else %} + </span> +{% endif %} diff --git a/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html b/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html index 8cc24aced1f57154d8ed8b5742e7e876ee7ba2c5..0296899df8782b86228dc8e15e40b07f612aab5f 100644 --- a/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html +++ b/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html @@ -27,7 +27,7 @@ </a> <div class="mb-6"> - {% include 'styleguide2/includes/molecules/tags/inline_tags.html' with tags=article.get_tags %} + {% include 'styleguide2/includes/molecules/tags/inline_tags.html' with tags=article.get_tags tags_are_selectable=True %} </div> <div class="flex flex-col justify-between h-full"> diff --git a/shared/templates/styleguide2/includes/molecules/tags/inline_tags.html b/shared/templates/styleguide2/includes/molecules/tags/inline_tags.html index 8e0e850c00f4d40808f9350c76e2cbf4bbf9a3ac..f6cae90e6352a0cbca2649a47f99bd964be0583e 100644 --- a/shared/templates/styleguide2/includes/molecules/tags/inline_tags.html +++ b/shared/templates/styleguide2/includes/molecules/tags/inline_tags.html @@ -1,5 +1,5 @@ <div class="flex gap-3 flex-wrap {{ classes }}"> {% for tag in tags %} - {% include 'styleguide2/includes/atoms/tags/tag.html' with text=tag %} + {% include 'styleguide2/includes/atoms/tags/tag.html' with text=tag.name id=tag.id %} {% endfor %} </div> diff --git a/shared/templates/styleguide2/includes/molecules/tags/tags.html b/shared/templates/styleguide2/includes/molecules/tags/tags.html index b4204e93c7948dd05f3b8dd696810be51931bc6b..96d952c1d7a277b6f52be32e5b2f1836ee6172f1 100644 --- a/shared/templates/styleguide2/includes/molecules/tags/tags.html +++ b/shared/templates/styleguide2/includes/molecules/tags/tags.html @@ -1,7 +1,23 @@ -<div class="flex gap-2 flex-wrap max-w-[550px] {{ classes }}"> +<div + class=" + flex gap-2 flex-wrap + + {% if size_classes %} + max-w-[550px] + {% else %} + {{ size_classes }} + {% endif %} + + {{ classes }} + " +> {% for tag in tags %} - {% include 'styleguide2/includes/atoms/tags/tag.html' with text=tag id=tag.id color_classes=tag_color_classes%} + {% include 'styleguide2/includes/atoms/tags/tag.html' with text=tag.name id=tag.id color_classes=tag_color_classes%} {% endfor %} + + {% if extra_tag and extra_tag not in tags %} + {% include 'styleguide2/includes/atoms/tags/tag.html' with text=extra_tag.name id=extra_tag.id color_classes=tag_color_classes %} + {% endif %} </div> {% if filtered_tag %} diff --git a/shared/templates/styleguide2/includes/organisms/header/articles_header.html b/shared/templates/styleguide2/includes/organisms/header/articles_header.html index d9f9c11eff7ff646ac3d6a6eaa0ed632f2bd3e3d..7c2366d47c2429c3ffff9819a44b176d8c432040 100644 --- a/shared/templates/styleguide2/includes/organisms/header/articles_header.html +++ b/shared/templates/styleguide2/includes/organisms/header/articles_header.html @@ -9,15 +9,17 @@ {% endblock %} {% block after_heading %} - {% include 'styleguide2/includes/molecules/tags/tags.html' with classes='mb-4' tags_are_selectable=True %} + {% include 'styleguide2/includes/molecules/tags/tags.html' with classes='mb-4' size_classes='' tags_are_selectable=True extra_tag=filtered_tag %} <form - class="flex justify-start" + class="flex flex-col gap-4 items-start justify-start" method="get" + name="searchForm" > <input type="text" name="q" + id="search_query" {% if search_query %} value="{{ search_query }}" @@ -26,5 +28,22 @@ class="max-w-md w-full bg-grey-180 px-4 py-2 text-black" placeholder="Hledej..." > + + {% if search_query %} + <span + class="text-white underline cursor-pointer" + id="reset-search" + >Vymazat vyhledávání</span> + + <script> + const resetSearch = (event) => { + event.preventDefault(); + document.getElementById('search_query').value = ""; + document.searchForm.submit(); + } + + document.getElementById("reset-search").onclick = resetSearch + </script> + {% endif %} </form> {% endblock %} diff --git a/shared/templates/styleguide2/includes/organisms/header/elections/articles_header.html b/shared/templates/styleguide2/includes/organisms/header/elections/articles_header.html index 1379dab55bb9cb6f6b2c533b6990eab07eb77679..73977995a53b8f874d4de82939899ddce1596008 100644 --- a/shared/templates/styleguide2/includes/organisms/header/elections/articles_header.html +++ b/shared/templates/styleguide2/includes/organisms/header/elections/articles_header.html @@ -11,7 +11,7 @@ {% endblock %} {% block after_heading %} - {% include 'styleguide2/includes/molecules/tags/tags.html' with classes='mb-4' tag_color_classes='bg-black text-white' reset_classes='text-black' tags_are_selectable=True %} + {% include 'styleguide2/includes/molecules/tags/tags.html' with classes='mb-4' tag_color_classes='bg-black text-white' size_classes='' reset_classes='text-black' tags_are_selectable=True extra_tag=filtered_tag %} <form class="flex justify-start" diff --git a/shared/templates/styleguide2/people_page.html b/shared/templates/styleguide2/people_page.html new file mode 100644 index 0000000000000000000000000000000000000000..a407a5c3596c37a27d5c7e39d9968394ae141f1c --- /dev/null +++ b/shared/templates/styleguide2/people_page.html @@ -0,0 +1,66 @@ +{% extends "styleguide2/base.html" %} +{% load wagtailcore_tags wagtailimages_tags shared_filters %} + +{% block content %} +{% include 'styleguide2/includes/organisms/layout/navbar.html' with selected_item=page.get_menu_title %} + +<div class="__js-root"> + <ui-view-provider + :initial="{ {% for people_group in page.people %}'{{ people_group.value.slug }}-{{ forloop.counter }}': {% if forloop.counter0 %}false{% else %}true{% endif %},{% endfor %} }" + :sync-location="true" + v-slot="{ isCurrentView, toggleView }" + > + {% include 'styleguide2/includes/organisms/header/people_header.html' with people=page.people title=page.title description_column_1=page.perex_col_1 description_column_2=page.perex_col_2 %} + + <main role="main" class="mb-20"> + <div class="container--wide"> + <div + class=" + flex flex-wrap justify-center gap-4 + xl:justify-start + " + > + <div class="grid grid-cols-1 gap-4 md:grid-cols-2 w-full"> + {% for block in page.people %} + {% if block.block_type == "people_group" %} + <template v-if="isCurrentView('{{ block.value.slug }}-{{ forloop.counter }}')"> + {% for person_page in block.value.person_list %} + {% image person_page.profile_image fill-480x480 as profile_image %} + + {% include 'styleguide2/includes/molecules/contact/contact_person_large_box.html' with image=profile_image name=person_page.title function=person_page.position telephone=person_page.phone mail=person_page.email url=person_page.url %} + {% endfor %} + </template> + {% endif %} + {% endfor %} + </div> + + {% for block in page.people %} + {% if block.block_type == "team_group" %} + <template v-if="isCurrentView('{{ block.value.slug }}-{{ forloop.counter }}')"> + {% for team in block.value.team_list %} + + {% if team.headline %} + <h2 class="head-6xl mt-5 mb-5">{{ team.headline }}</h2> + {% endif %} + + <ul class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 content-stretch gap-8"> + {% for card in team.card_items %} + {% image card.image max-512x512 as card_image %} + {% firstof card.page.url card.link as card_url %} + + {% include 'styleguide2/includes/molecules/boxes/card_box.html' with image=card_image header=card.title content=card.text url=card_url description_classes='!bg-grey-180' %} + {% endfor %} + </ul> + {% endfor %} + </template> + {% endif %} + {% endfor %} + </div> + </div> + </main> + </ui-view-provider> +</div> + +{% include 'styleguide2/includes/organisms/main_section/newsletter_section.html' %} + +{% endblock content %}