from captcha.fields import CaptchaField from django.db import models from django.shortcuts import redirect from django.utils.translation import gettext_lazy from modelcluster.contrib.taggit import ClusterTaggableManager from modelcluster.fields import ParentalKey, ParentalManyToManyField from taggit.models import TaggedItemBase from wagtail import blocks from wagtail.admin.panels import ( FieldPanel, InlinePanel, MultiFieldPanel, ObjectList, PageChooserPanel, TabbedInterface, ) from wagtail.contrib.forms.models import AbstractForm, AbstractFormField from wagtail.contrib.forms.panels import FormSubmissionsPanel from wagtail.fields import RichTextField, StreamField from wagtail.models import Page from wagtailmetadata.models import MetadataPageMixin from calendar_utils.models import CalendarMixin from shared.blocks import ( DEFAULT_CONTENT_BLOCKS, CalendarBlock, NavbarMenuItemBlock, NewsBlock, NewsletterSubscriptionBlock, ) from shared.const import RICH_TEXT_DEFAULT_FEATURES from shared.models import ( CalendarMixin, CustomLogoMixin, EcomailNewsletterMixin, ExtendedMetadataPageMixin, FbEventsMixin, MainArticlePageMixin, MainArticlesPageMixin, MainHomePageMixin, MainMenuMixin, MainPeoplePageMixin, MainPersonPageMixin, MainSearchPageMixin, PageInMenuMixin, PdfPageMixin, ScrollProgressMixin, SharedTaggedUniwebArticle, SocialMixin, SubpageMixin, ) from shared.utils import subscribe_to_ecomail_newsletter from shared_legacy.models import FooterMixin as LegacyFooterMixin from shared_legacy.utils import make_promote_panels from .blocks import PeopleGroupBlock, TeamBlock, UniwebSubpageFormBlock from .forms import UniwebArticlesPageForm, UniwebHomePageAdminForm CONTENT_STREAM_BLOCKS = DEFAULT_CONTENT_BLOCKS + [ ("calendar", CalendarBlock()), ("subpage_form", UniwebSubpageFormBlock()), ] class UniwebArticleTag(TaggedItemBase): content_object = ParentalKey( "uniweb.UniwebArticlePage", on_delete=models.CASCADE, related_name="tagged_items", ) class UniwebHomePage( CalendarMixin, LegacyFooterMixin, PageInMenuMixin, ScrollProgressMixin, CustomLogoMixin, EcomailNewsletterMixin, FbEventsMixin, MainHomePageMixin, ): base_form_class = UniwebHomePageAdminForm ### FIELDS show_transparent_header = models.BooleanField( default=False, verbose_name="Průhledná hlavička?", help_text=( "Pokud je toto pole zaškrtlé, obrázek na pozadí hlavičky " "se neztmaví." ), ) main_image = models.ForeignKey( "wagtailimages.Image", on_delete=models.PROTECT, blank=True, null=True, verbose_name="Obrázek na pozadí hlavičky", related_name="+", ) menu_button_name = models.CharField( verbose_name="Text na tlačítku pro zapojení", max_length=16 ) menu_button_content = StreamField( [ ("navbar_menu_item", NavbarMenuItemBlock()), ], verbose_name="Obsah tlačítka pro zapojení", blank=True, use_json_field=True, ) calendar_page = models.ForeignKey( "UniwebCalendarPage", verbose_name="Stránka s kalendářem", on_delete=models.PROTECT, null=True, blank=True, ) content = StreamField( CONTENT_STREAM_BLOCKS + [ ("newsletter", NewsletterSubscriptionBlock()), ( "news_block", NewsBlock( template="styleguide2/includes/organisms/articles/district/articles_section.html", group="3. Ostatní", ), ), ], verbose_name="obsah stránky", blank=True, use_json_field=True, ) hide_footer = models.BooleanField( "skrýt patičku", default=False, help_text="Chcete skrýt patičku?" ) show_logo = models.BooleanField( "zobrazit logo", default=True, help_text="Chcete v hlavičce ukazovat logo?" ) calendar_button_text = models.CharField( "Text tlačítka kalendáře", max_length=256, default="Kalendář" ) footer_extra_content = RichTextField( verbose_name="Extra obsah pod šedou patičkou", blank=True, features=RICH_TEXT_DEFAULT_FEATURES, ) content_is_full_width = models.BooleanField( "Roztáhnout obsah na celou šířku stránky", default=False ) content_is_centered = models.BooleanField("Vycentrovat obsah", default=False) newsletter_list_id = models.CharField( "ID Mailtrain newsletteru", max_length=20, blank=True, null=True, help_text="ID newsletteru z Mailtrainu. Po vyplnění se formulář pro odběr newsletteru zobrazí na úvodní stránce a na stránce s kontakty.", ) ### PANELS content_panels = MainHomePageMixin.content_panels + [ FieldPanel("main_image"), FieldPanel("show_transparent_header"), ] settings_panels = [ MultiFieldPanel( [ FieldPanel("matomo_id"), FieldPanel("title_suffix"), FieldPanel("meta_title_suffix"), ], "Obecné nastavení webu", ), MultiFieldPanel( [ FieldPanel("calendar_url"), PageChooserPanel("calendar_page"), ], "Kalendář", ), MultiFieldPanel( [ FieldPanel("content_is_full_width"), FieldPanel("content_is_centered"), ], "Zarovnání obsahu", ), MultiFieldPanel( [ FieldPanel("ecomail_newsletter_list_id"), FieldPanel("ecomail_newsletter_list_tags"), FieldPanel("ecomail_newsletter_list_source"), FieldPanel("newsletter_list_id"), ], "Newsletter", ), FieldPanel("fallback_image"), FieldPanel("fbevents_id"), ] + ScrollProgressMixin.settings_panels menu_panels = ( [ MultiFieldPanel( [ FieldPanel("dark_logo"), FieldPanel("light_logo"), FieldPanel("show_logo"), ], "Logo", ) ] + MainMenuMixin.menu_panels + SocialMixin.menu_panels + [ FieldPanel("menu_button_name"), FieldPanel("menu_button_content"), FieldPanel("calendar_button_text"), ] ) footer_panels = [ FieldPanel("hide_footer"), FieldPanel("footer_extra_content"), ] + MainHomePageMixin.footer_panels edit_handler = TabbedInterface( [ ObjectList(content_panels, heading="Obsah"), ObjectList(menu_panels, heading="Hlavička"), ObjectList(footer_panels, heading="Patička"), ObjectList(settings_panels, heading="Nastavení"), ObjectList(MainHomePageMixin.promote_panels, heading="Metadata"), ] ) ### RELATIONS subpage_types = [ "uniweb.UniwebFlexiblePage", "uniweb.UniwebArticlesIndexPage", "uniweb.UniwebFormPage", "uniweb.UniwebPeoplePage", "uniweb.UniwebCalendarPage", "uniweb.UniwebSearchPage", ] ### OTHERS class Meta: verbose_name = "Univerzální web" @property def gdpr_and_cookies_page(self): from main.models import MainHomePage return MainHomePage.objects.first().gdpr_and_cookies_page @property def article_page_model(self): return UniwebArticlePage @property def articles_page_model(self): return UniwebArticlesIndexPage @property def people_page_model(self): return UniwebPeoplePage @property def search_page_model(self): return UniwebSearchPage @property def root_page(self): return self @property def has_calendar(self): return self.calendar_id is not None class UniwebFlexiblePage( PageInMenuMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, ScrollProgressMixin, Page, ): ### FIELDS show_transparent_header = models.BooleanField( default=False, verbose_name="Průhledná hlavička?", help_text=( "Pokud je toto pole zaškrtlé, obrázek na pozadí hlavičky " "se neztmaví." ), ) main_image = models.ForeignKey( "wagtailimages.Image", on_delete=models.PROTECT, blank=True, null=True, verbose_name="Obrázek na pozadí hlavičky", related_name="+", ) content = StreamField( CONTENT_STREAM_BLOCKS + [("newsletter", NewsletterSubscriptionBlock())], verbose_name="obsah stránky", blank=True, use_json_field=True, ) ### PANELS promote_panels = make_promote_panels() content_panels = Page.content_panels + [ FieldPanel("content"), FieldPanel("main_image"), FieldPanel("show_transparent_header"), ] edit_handler = TabbedInterface( [ ObjectList(content_panels, heading="Obsah"), ObjectList(ScrollProgressMixin.settings_panels, heading="Nastavení"), ObjectList(promote_panels, heading="Metadata"), ] ) ### RELATIONS parent_page_types = [ "uniweb.UniwebHomePage", "uniweb.UniwebFlexiblePage", "uniweb.UniwebFormPage", ] subpage_types = [ "uniweb.UniwebFlexiblePage", "uniweb.UniwebFormPage", ] ### OTHERS class Meta: verbose_name = "Flexibilní stránka" class UniwebCalendarPage( PageInMenuMixin, SubpageMixin, MetadataPageMixin, CalendarMixin, Page ): """ Page for displaying full calendar """ ### PANELS content_panels = Page.content_panels + [FieldPanel("calendar_url")] ### RELATIONS parent_page_types = [ "uniweb.UniwebHomePage", ] subpage_types = [] ### OTHERS class Meta: verbose_name = "Stránka s kalendářem" class UniwebArticlesIndexPage(MainArticlesPageMixin): base_form_class = UniwebArticlesPageForm displayed_tags = ParentalManyToManyField( "uniweb.UniwebArticleTag", verbose_name="Z tohoto webu", related_name="+", blank=True, ) displayed_shared_tags = ParentalManyToManyField( "shared.SharedTag", verbose_name="Sdílecí", related_name="+", blank=True, ) ### RELATIONS parent_page_types = ["uniweb.UniwebHomePage"] subpage_types = ["uniweb.UniwebArticlePage"] ### PANELS edit_handler = TabbedInterface( [ ObjectList(MainArticlesPageMixin.content_panels, heading="Obsah"), ObjectList(MainArticlesPageMixin.promote_panels, heading="Metadata"), ] ) class UniwebArticlePage(MainArticlePageMixin): author_page = models.ForeignKey( "uniweb.UniwebPersonPage", on_delete=models.SET_NULL, null=True, blank=True ) tags = ClusterTaggableManager(through=UniwebArticleTag, blank=True) shared_tags = ClusterTaggableManager( verbose_name="Štítky pro sdílení mezi weby", through=SharedTaggedUniwebArticle, blank=True, ) ### RELATIONS parent_page_types = ["uniweb.UniwebArticlesIndexPage"] subpage_types = ["uniweb.UniwebPdfPage"] class UniwebFormField(AbstractFormField): page = ParentalKey( "UniwebFormPage", on_delete=models.CASCADE, related_name="form_fields" ) class UniwebFormPage( AbstractForm, PageInMenuMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page, ): ### FIELDS show_transparent_header = models.BooleanField( default=False, verbose_name="Průhledná hlavička?", help_text=( "Pokud je toto pole zaškrtlé, obrázek na pozadí hlavičky " "se neztmaví." ), ) main_image = models.ForeignKey( "wagtailimages.Image", on_delete=models.PROTECT, blank=True, null=True, verbose_name="Obrázek na pozadí hlavičky", related_name="+", ) content_before = StreamField( CONTENT_STREAM_BLOCKS, verbose_name="obsah stránky před formulářem", blank=True, use_json_field=True, ) content_after = StreamField( CONTENT_STREAM_BLOCKS, verbose_name="obsah stránky za formulářem", blank=True, use_json_field=True, ) content_landing = StreamField( CONTENT_STREAM_BLOCKS, verbose_name="Obsah stránky zobrazené po odeslání formuláře", blank=True, use_json_field=True, ) show_in_parent_page = models.BooleanField( verbose_name="Ukazovat obsah formuláře v nadřazené stránce?", default=False, help_text=( "Pokud je toto pole zaškrtnuté, formulář se přesune do nadřazené stránky " "a stránka jemu nadřazená bude nedostupná." ), ) subscribe_to_ecomail = models.BooleanField( verbose_name="Automaticky odebírat vyplněné údaje do Ecomail NL?", default=False, ) name_and_surname_field_id = models.CharField( verbose_name="ID jméno & příjmení fieldu", blank=True, null=True ) email_field_id = models.CharField( verbose_name="ID email fieldu", blank=True, null=True ) submission_button_text = models.CharField( verbose_name="Text tlačítka pro odeslání formuláře", default="Odeslat", ) ### PANELS content_panels = AbstractForm.content_panels + [ FieldPanel("main_image"), FieldPanel("show_transparent_header"), FieldPanel("content_before"), InlinePanel("form_fields", label="formulář"), FieldPanel("submission_button_text"), FieldPanel("content_after"), FieldPanel("content_landing"), ] promote_panels = make_promote_panels() submissions_panels = [FormSubmissionsPanel()] advanced_panels = [ FieldPanel("show_in_parent_page"), FieldPanel("subscribe_to_ecomail"), FieldPanel("name_and_surname_field_id"), FieldPanel("email_field_id"), ] edit_handler = TabbedInterface( [ ObjectList(content_panels, heading=gettext_lazy("Content")), ObjectList(promote_panels, heading=gettext_lazy("Promote")), ObjectList(advanced_panels, heading="Pokročilé"), ObjectList(submissions_panels, heading="Data z formuláře"), ] ) ### RELATIONS parent_page_types = [ "uniweb.UniwebHomePage", "uniweb.UniwebFlexiblePage", "uniweb.UniwebFormPage", ] subpage_types = ["uniweb.UniwebFlexiblePage", "uniweb.UniwebFormPage"] ### OTHERS def serve(self, request): if request.method == "GET" and self.show_in_parent_page: if hasattr(self, "root_page"): return redirect(self.root_page.url) else: return redirect("/") return super().serve(request) def process_form_submission(self, form): cleaned_data = form.cleaned_data if ( hasattr(self, "root_page") and self.root_page and self.subscribe_to_ecomail and self.name_and_surname_field_id in cleaned_data and self.email_field_id in cleaned_data ): name_and_surname = cleaned_data[self.name_and_surname_field_id] name_and_surname = name_and_surname.split(" ") name = "" surname = "" if len(name_and_surname) > 1: name = name_and_surname[0] surname = " ".join(name_and_surname[1:]) else: name = name_and_surname[0] custom_data = { "name": name, } if surname != "": custom_data["surname"] = surname subscribe_to_ecomail_newsletter( cleaned_data[self.email_field_id], self.root_page.ecomail_newsletter_list_tags, self.root_page.ecomail_newsletter_list_source, self.root_page.ecomail_newsletter_list_id, custom_data, ) super().process_form_submission(form) class Meta: verbose_name = "Formulářová stránka" def get_form_class(self): form = super().get_form_class() form.base_fields["captcha"] = CaptchaField(label="opište písmena z obrázku") return form class UniwebPersonPage(MainPersonPageMixin): ### FIELDS job = models.CharField( "Povolání", max_length=128, blank=True, null=True, help_text="Např. 'Informatik'", ) city = models.CharField("Město/obec", max_length=64, blank=True, null=True) age = models.IntegerField("Věk", blank=True, null=True) is_pirate = models.BooleanField("Je členem Pirátské strany?", default=True) other_party = models.CharField( "Strana", max_length=64, blank=True, null=True, help_text="Vyplňte pokud osoba není Pirát", ) other_party_logo = models.ForeignKey( "wagtailimages.Image", on_delete=models.PROTECT, blank=True, null=True, related_name="+", verbose_name="Logo strany", help_text="Vyplňte pokud osoba není Pirát", ) ### PANELS content_panels = Page.content_panels + [ MultiFieldPanel( [ FieldPanel("main_image"), FieldPanel("profile_image"), ], heading="Obrázky", ), MultiFieldPanel( [FieldPanel("before_name"), FieldPanel("after_name")], heading="Titul", ), MultiFieldPanel( [ FieldPanel("is_pirate"), FieldPanel("other_party"), FieldPanel("other_party_logo"), ], heading="Politická příslušnost", ), MultiFieldPanel( [ FieldPanel("position"), FieldPanel("job"), FieldPanel("city"), FieldPanel("age"), ], heading="Základní informace", ), MultiFieldPanel([FieldPanel("perex"), FieldPanel("text")], heading="Popis"), MultiFieldPanel( [ FieldPanel("email"), FieldPanel("phone"), FieldPanel("social_links"), ], heading="Kontakt", ), FieldPanel("calendar_url"), FieldPanel("related_people"), ] ### RELATIONS parent_page_types = ["uniweb.UniwebPeoplePage"] subpage_types = [] class UniwebPeoplePage(MainPeoplePageMixin): ### FIELDS content = StreamField( [ ( "text", blocks.RichTextBlock( label="Textový editor", features=RICH_TEXT_DEFAULT_FEATURES, template="styleguide2/includes/atoms/text/prose_richtext.html", ), ), ("people_group", PeopleGroupBlock()), ("team_group", TeamBlock()), ], verbose_name="Obsah stránky", blank=True, use_json_field=True, ) ### RELATIONS parent_page_types = ["uniweb.UniwebHomePage"] subpage_types = ["uniweb.UniwebPersonPage"] class UniwebPdfPage( PageInMenuMixin, MetadataPageMixin, SubpageMixin, PdfPageMixin, Page ): """ Single pdf page display """ ### RELATIONS parent_page_types = [ "uniweb.UniwebHomePage", "uniweb.UniwebArticlePage", ] subpage_types = [] ### PANELS content_panels = Page.content_panels + PdfPageMixin.content_panels ### OTHER class Meta: verbose_name = "PDF stránka" class UniwebSearchPage(MainSearchPageMixin): ### RELATIONS parent_page_types = ["uniweb.UniwebHomePage"] ### OTHER @property def searchable_models(self): return [ UniwebArticlePage, UniwebPersonPage, UniwebFlexiblePage, ]