from django.db import models from django.shortcuts import redirect from django.template.loader import render_to_string from modelcluster.contrib.taggit import ClusterTaggableManager from modelcluster.fields import ParentalKey from taggit.models import TaggedItemBase from wagtail.admin.panels import FieldPanel, ObjectList, TabbedInterface from wagtail.blocks import RichTextBlock from wagtail.contrib.routable_page.models import route from wagtail.fields import RichTextField, StreamField from wagtail.models import Page from wagtailmetadata.models import MetadataPageMixin from calendar_utils.models import CalendarMixin from shared import blocks as shared_blocks from shared.models import ( # MenuMixin, ArticleMixin, ExtendedMetadataHomePageMixin, ExtendedMetadataPageMixin, MainArticlePageMixin, MainArticlesPageMixin, MainContactPageMixin, MainHomePageMixin, MainSearchPageMixin, MainSimplePageMixin, PageInMenuMixin, SharedTaggedElectionsArticle, SubpageMixin, ) from shared.utils import make_promote_panels from . import blocks from .forms import JekyllImportForm class ElectionsHomePage(MainHomePageMixin, CalendarMixin): # content content = StreamField( [ ("carousel", blocks.ElectionsCarouselBlock()), ("candidates", blocks.CandidateListBlock()), ("secondary_candidates", blocks.CandidateSecondaryListBlock()), ("program", shared_blocks.CarouselProgramBlock()), ( "news", shared_blocks.NewsBlock( template="styleguide2/includes/organisms/articles/elections/articles_section.html" ), ), ("calendar", blocks.CalendarBlock()), ], verbose_name="Hlavní obsah", blank=True, use_json_field=True, ) # settings gdpr_and_cookies_page = models.ForeignKey( # Keep this a reference to the main website's GDPR page. Not ideal, but works (for now). "main.MainSimplePage", verbose_name="Stránka pro GDPR", on_delete=models.PROTECT, blank=True, null=True, ) subpage_types = [ "elections.ElectionsArticlesPage", "elections.ElectionsCandidatesPage", "elections.ElectionsFaqPage", "elections.ElectionsSearchPage", "elections.ElectionsFullProgramPage", "elections.ElectionsSimplePage", ] settings_panels = MainHomePageMixin.settings_panels + [FieldPanel("calendar_url")] edit_handler = TabbedInterface( [ ObjectList(MainHomePageMixin.content_panels, heading="Obsah"), ObjectList(MainHomePageMixin.promote_panels, heading="Metadata"), ObjectList(settings_panels, heading="Nastavení"), ObjectList(MainHomePageMixin.menu_panels, heading="Menu"), ] ) ### OTHERS class Meta: verbose_name = "Volební web" @property def article_page_model(self): return ElectionsArticlePage @property def articles_page_model(self): return ElectionsArticlesPage @property 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 def _first_subpage_of_type(self, page_type) -> Page or None: try: return self.get_descendants().type(page_type).live().specific()[0] except IndexError: return None @route(r"^sdilene/$", name="shared") def shared(self, request): return self.setup_article_page_context(request) class ElectionsArticlesPage(MainArticlesPageMixin): base_form_class = JekyllImportForm parent_page_types = ["elections.ElectionsHomePage"] subpage_types = ["elections.ElectionsArticlePage"] class ElectionsArticleTag(TaggedItemBase): content_object = ParentalKey( "elections.ElectionsArticlePage", on_delete=models.CASCADE, related_name="elections_tagged_items", ) class ElectionsArticlePage(MainArticlePageMixin): author_page = models.ForeignKey( "elections.ElectionsCandidatePage", on_delete=models.SET_NULL, null=True, blank=True, verbose_name="Stránka autora (kandidáta)", ) tags = ClusterTaggableManager( through=ElectionsArticleTag, related_name="elections_tagged_articles", blank=True, ) shared_tags = ClusterTaggableManager( verbose_name="Tagy pro sdílení mezi weby", through=SharedTaggedElectionsArticle, blank=True, ) parent_page_types = ["elections.ElectionsArticlesPage"] subpage_types = [] class ElectionsSearchPage(MainSearchPageMixin): parent_page_types = ["elections.ElectionsHomePage"] subpage_types = [] @property def searchable_models(self) -> list: return [ ElectionsArticlePage, ElectionsCandidatePage, ] class ElectionsCandidatesPage( ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page, ): parent_page_types = ["elections.ElectionsHomePage"] subpage_types = ["elections.ElectionsCandidatePage"] def serve(self, request, *args, **kwargs): return redirect(self.root_page.url) class Meta: verbose_name = "Kandidáti" class ElectionsCandidatePage( ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page, ): ## FIELDS image = models.ForeignKey( "wagtailimages.Image", on_delete=models.PROTECT, blank=True, null=True, verbose_name="Obrázek", related_name="+", ) position = models.CharField("Pozice/povolání", max_length=64, blank=True, null=True) perex = RichTextField() description = RichTextField("Popis", blank=True, null=True) email = models.CharField("E-mail", max_length=128, blank=True, null=True) phone = models.CharField("Telefonní kontakt", max_length=16, blank=True, null=True) social_links = StreamField( [ ("social_links", shared_blocks.SocialLinkBlock()), ], verbose_name="Odkazy na sociální sítě", blank=True, use_json_field=True, ) articles_heading = models.CharField( "Nadpis sekce s články", max_length=32, help_text='Např. "Aktuality Mikuláše Peksy".', ) ## PANELS content_panels = Page.content_panels + [ FieldPanel("image"), FieldPanel("position"), FieldPanel("perex"), FieldPanel("description"), FieldPanel("email"), FieldPanel("phone"), FieldPanel("social_links"), FieldPanel("articles_heading"), ] promote_panels = make_promote_panels() ## RELATIONS parent_page_types = ["elections.ElectionsCandidatesPage"] subpage_types = [] ## META class Meta: verbose_name = "Kandidát" ## FUNCTIONS def get_context(self, request) -> dict: context = super().get_context(request) context["related_candidates_list"] = ( ElectionsCandidatePage.objects.filter(~models.Q(id=self.id)) .order_by("?") .live()[:3] ) context["article_data_list"] = ( ElectionsArticlePage.objects.filter(author_page=self.id) .order_by("-timestamp") .live()[:3] ) return context class ElectionsFaqPage( ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page, ): ## FIELDS # content content = StreamField( [ ("person_answers", blocks.PersonFaqAnswersBlock()), ], verbose_name="Obsah", blank=True, use_json_field=True, ) all_topics_name = models.CharField( "Nadpis štítku pro všechna témata", max_length=32, help_text="např. 'všechna témata'", ) ## PANELS content_panels = Page.content_panels + [ FieldPanel("content"), FieldPanel("all_topics_name"), ] promote_panels = make_promote_panels() ## RELATIONS parent_page_types = ["elections.ElectionsHomePage"] subpage_types = [] class Meta: verbose_name = "Otázky a odpovědi" ## OTHERS def get_topic_names(self) -> list: topic_names = [self.all_topics_name] for section in self.content: topic_names.append(section.value["topic"]) return topic_names class ElectionsFullProgramPage( ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page, ): content = StreamField( [ ("richtext", RichTextBlock(label="Text", template="styleguide2/includes/atoms/text/prose_richtext.html")), ("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" ## OTHERS def get_main_page_program_render(self): for block in self.content: if block.block_type == "popout_block": return render_to_string( "styleguide2/includes/organisms/popouts/popout_list.html", {"categories": block.value["categories"]}, ) return "" class ElectionsSimplePage(MainSimplePageMixin): parent_page_types = [ "elections.ElectionsHomePage", "elections.ElectionsSimplePage", ] subpage_types = ["elections.ElectionsSimplePage"]