Skip to content
Snippets Groups Projects
models.py 28.14 KiB
from functools import cached_property

from dateutil.relativedelta import relativedelta
from django.conf import settings
from django.contrib import messages
from django.core.paginator import Paginator
from django.db import models
from django.forms.models import model_to_dict
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from django.utils import timezone
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import Tag, TaggedItemBase
from wagtail.admin.panels import (
    FieldPanel,
    HelpPanel,
    MultiFieldPanel,
    ObjectList,
    PageChooserPanel,
    TabbedInterface,
)
from wagtail.blocks import PageChooserBlock, RichTextBlock
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.fields import RichTextField, StreamField
from wagtail.models import Page
from wagtail.search import index
from wagtailmetadata.models import MetadataPageMixin

from calendar_utils.models import CalendarMixin
from shared.forms import SubscribeForm
from shared.models import (  # MenuMixin,
    ArticleMixin,
    ArticlesMixin,
    ArticlesPageMixin,
    ExtendedMetadataHomePageMixin,
    ExtendedMetadataPageMixin,
    SharedTaggedMainArticle,
    SubpageMixin,
)
from shared.utils import make_promote_panels, subscribe_to_newsletter
from tuning import admin_help

from . import blocks
from .constants import MONTH_NAMES
from .forms import JekyllImportForm
from .menu import MenuMixin, PageInMenuMixin


class MainHomePage(
    MenuMixin,
    RoutablePageMixin,
    ExtendedMetadataHomePageMixin,
    MetadataPageMixin,
    ArticlesMixin,
    Page,
):
    # header

    menu_button_name = models.CharField(
        verbose_name="Text na tlačítku pro zapojení", max_length=16
    )

    menu_button_content = StreamField(
        [
            ("navbar_menu_item", blocks.NavbarMenuItemBlock()),
        ],
        verbose_name="Obsah menu pro zapojení se",
        blank=True,
        use_json_field=True,
    )

    # content
    content = StreamField(
        [
            ("carousel", blocks.HomePageCarouseSlideBlock()),
            ("news", blocks.NewsBlock()),
            ("europarl_news", blocks.EuroparlNewsBlock()),
            ("people", blocks.PeopleOverviewBlock()),
            ("regions", blocks.RegionsBlock()),
            ("boxes", blocks.BoxesBlock()),
        ],
        verbose_name="Hlavní obsah",
        blank=True,
        use_json_field=True,
    )

    # footer
    footer_other_links = StreamField(
        [
            ("other_links", blocks.OtherLinksBlock()),
        ],
        verbose_name="Odkazy v zápatí webu",
        blank=True,
        use_json_field=True,
    )

    footer_person_list = StreamField(
        [("person", blocks.PersonContactBlock())],
        verbose_name="Osoby v zápatí webu",
        blank=True,
        max_num=6,
        use_json_field=True,
    )

    # settings
    gdpr_and_cookies_page = models.ForeignKey(
        "main.MainSimplePage",
        verbose_name="Stránka pro GDPR",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )

    matomo_id = models.IntegerField(
        "Matomo ID pro sledování návštěvnosti", blank=True, null=True
    )

    social_links = StreamField(
        [
            ("social_links", blocks.SocialLinkBlock()),
        ],
        verbose_name="Odkazy na sociální sítě",
        blank=True,
        use_json_field=True,
    )

    content_panels = Page.content_panels + [
        FieldPanel("content"),
        FieldPanel("footer_other_links"),
        FieldPanel("footer_person_list"),
    ]

    promote_panels = make_promote_panels(admin_help.build(admin_help.IMPORTANT_TITLE))

    settings_panels = [
        FieldPanel("menu_button_name"),
        FieldPanel("menu_button_content"),
        PageChooserPanel("gdpr_and_cookies_page"),
        FieldPanel("social_links"),
        FieldPanel("matomo_id"),
    ]

    ### EDIT HANDLERS

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading="Obsah"),
            ObjectList(promote_panels, heading="Propagovat"),
            ObjectList(settings_panels, heading="Nastavení"),
            ObjectList(MenuMixin.menu_panels, heading="Menu"),
        ]
    )

    ### RELATIONS

    subpage_types = [
        "main.MainArticlesPage",
        "main.MainProgramPage",
        "main.MainPeoplePage",
        "main.MainPersonPage",
        "main.MainSimplePage",
        "main.MainContactPage",
        "main.MainCrossroadPage",
        "main.MainHoaxPage",
        "main.MainSearchPage",
    ]

    ### OTHERS

    class Meta:
        verbose_name = "HomePage pirati.cz"

    @cached_property
    def gdpr_and_cookies_url(self):
        if self.gdpr_and_cookies_page:
            return self.gdpr_and_cookies_page.url
        return "#"

    @staticmethod
    def get_404_response(request):
        return render(request, "main/404.html", status=404)

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, args, kwargs)

        context["article_data_list"] = self.materialize_shared_articles_query(
            self.append_all_shared_articles_query(MainArticlePage.objects.live().all())
            .live()
            .order_by("-union_date")[:3]
        )

        return context

    def get_region_response(self, request):
        context = {}
        if request.GET.get("region", None) == "VSK":
            sorted_article_qs = MainArticlePage.objects.filter(
                region__isnull=False
            ).order_by("-date")
            context = {"article_data_list": sorted_article_qs[:3]}
        else:
            sorted_article_qs = MainArticlePage.objects.filter(
                region=request.GET.get("region", None)
            )[:3]
            context = {"article_data_list": sorted_article_qs[:3]}

        data = {
            "html": render(
                request, "main/includes/small_article_preview.html", context
            ).content.decode("utf-8")
        }

        return JsonResponse(data=data, safe=False)

    def serve(self, request, *args, **kwargs):
        if request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest":
            if "region" in request.GET:
                return self.get_region_response(request)

        return super().serve(request, *args, **kwargs)

    @cached_property
    def newsletter_subscribe_url(self):
        newsletter_subscribe = self.reverse_subpage("newsletter_subscribe")
        return (
            self.url + newsletter_subscribe
            if self.url is not None
            else newsletter_subscribe
        )  # preview fix

    @property
    def articles_page(self):
        return self._first_subpage_of_type(MainArticlesPage)

    @property
    def people_page(self):
        return self._first_subpage_of_type(MainPeoplePage)

    @property
    def contact_page(self):
        return self._first_subpage_of_type(MainContactPage)

    @property
    def search_page(self):
        return self._first_subpage_of_type(MainSearchPage)

    @property
    def root_page(self):
        return self

    @route(r"^prihlaseni-k-newsletteru/$")
    def newsletter_subscribe(self, request):
        if request.method == "POST":
            form = SubscribeForm(request.POST)
            if form.is_valid():
                subscribe_to_newsletter(
                    form.cleaned_data["email"], settings.PIRATICZ_NEWSLETTER_CID
                )

                messages.success(
                    request,
                    "Zkontroluj si prosím schránku, poslali jsme ti potvrzovací email.",
                )

                try:
                    page = (
                        Page.objects.filter(id=form.cleaned_data["return_page_id"])
                        .live()
                        .first()
                    )
                    return HttpResponseRedirect(page.full_url)
                except Page.DoesNotExist:
                    return HttpResponseRedirect(self.url)

            messages.error(
                request,
                "Tvůj prohlížeč nám odeslal špatná data. Prosím, zkus to znovu.",
            )

        return HttpResponseRedirect(self.url)

    @route(r"^feeds/atom/$")
    def view_feed(self, request):
        # Avoid circular import
        from .feeds import LatestArticlesFeed  # noqa

        return LatestArticlesFeed()(request, self.articles_page.id)

    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 MainArticlesPage(
    RoutablePageMixin,
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
    ArticlesPageMixin,
    PageInMenuMixin,
    Page,
):
    last_import_log = models.TextField(
        "Výstup z posledního importu", null=True, blank=True
    )
    perex = models.TextField()

    import_panels = [
        MultiFieldPanel(
            [
                FieldPanel("do_import"),
                FieldPanel("collection"),
                FieldPanel("dry_run"),
                FieldPanel("jekyll_repo_url"),
                FieldPanel("readonly_log"),
                HelpPanel(
                    "Import provádějte vždy až po vytvoření stránky aktualit. "
                    'Pro uložení logu je nutné volit možnost "Publikovat", nikoliv'
                    'pouze "Uložit koncept". '
                    "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",
        ),
    ]

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = ["main.MainArticlePage"]

    ### PANELS
    content_panels = Page.content_panels + [
        FieldPanel("perex"),
        FieldPanel("shared_tags"),
    ]
    promote_panels = make_promote_panels()

    ### EDIT HANDLERS

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading="Obsah"),
            ObjectList(promote_panels, heading="Propagovat"),
            ObjectList(import_panels, heading="Import"),
        ]
    )

    ### OTHERS

    base_form_class = JekyllImportForm

    class Meta:
        verbose_name = "Rozcestník článků"

    def get_base_shared_articles_query(self, filter: models.Q):
        return self.materialize_shared_articles_query(
            self.append_all_shared_articles_query(
                MainArticlePage.objects.filter(filter)
            )
            .live()
            .order_by("-union_date")
        )

    def get_article_data_list(
        self,
        months_back: int = 1,
        search_filter: models.Q | None = None,
    ):
        if search_filter is None:
            search_filter = models.Q()

        target_date_list = (
            self.append_all_shared_articles_query(
                MainArticlePage.objects.filter(search_filter)
            )
            .order_by("-union_date")
            .live()
            .values_list("union_date", flat=True)
        )

        if not target_date_list:
            return []

        target_date = target_date_list[0] - relativedelta(months=months_back)
        first_day_of_target_month = target_date.replace(day=1)

        filter = models.Q(date__gte=first_day_of_target_month) & search_filter

        sorted_article_qs = self.get_base_shared_articles_query(filter)

        article_data_list = []

        current_month_data = self.get_empty_month_data(timezone.now().date())

        for article in sorted_article_qs:
            if article.date.month != current_month_data["month_number"]:
                if len(current_month_data["articles"]) != 0:
                    # append completed month if it contains any articles
                    article_data_list.append(current_month_data)

                current_month_data = self.get_empty_month_data(article.date)

            current_month_data["articles"].append(article)

        article_data_list.append(current_month_data)  # last iteration

        return article_data_list

    def get_search_filters(self, request):
        filter = models.Q()

        if "tag_id" in request.GET:
            tag = self.get_filtered_tag(request)

            if tag is not None:
                filter = filter & models.Q(tags__id=tag.id)

        if "q" in request.GET:
            filter = filter & models.Q(title__icontains=self.get_search_query(request))

        return filter

    def get_filtered_tag(self, request) -> Tag | None:
        if "tag_id" in request.GET:
            try:
                return Tag.objects.filter(id=int(request.GET["tag_id"])).first()
            except Exception:
                pass

        return None

    def get_search_query(self, request) -> str | None:
        if "q" in request.GET:
            return request.GET["q"]

    def get_context(self, request, get_articles: bool = True, *args, **kwargs):
        ctx = super().get_context(request, args, kwargs)

        if get_articles:
            filtered_tag = self.get_filtered_tag(request)

            if filtered_tag is not None:
                ctx["filtered_tag"] = filtered_tag

            search_query = self.get_search_query(request)

            if search_query is not None:
                ctx["search_query"] = search_query

            search_filter = self.get_search_filters(request)

            article_timeline_list = self.get_article_data_list(1, search_filter)

            ctx["article_timeline_list"] = article_timeline_list
            ctx["show_next_timeline_articles"] = len(
                self.get_base_shared_articles_query(search_filter)
            ) != 0 and (
                self.materialize_shared_articles_query(
                    self.append_all_shared_articles_query(
                        MainArticlePage.objects.filter(search_filter)
                    )
                    .live()
                    .order_by("union_date")[:2]  # LIMIT 2
                )[0]
                not in article_timeline_list[-1]["articles"]
            )

            tags = []

            for article in MainArticlePage.objects.all()[:50]:
                for tag in article.tags.all():
                    if tag in tags:
                        continue

                    tags.append(tag)

            ctx["tags"] = tags

            # meow

        return ctx

    def get_timeline_articles_response(self, request):
        try:
            months = int(request.GET.get("months", None))
        except ValueError:
            months = 1

        search_filter = self.get_search_filters(request)
        article_timeline_list = self.get_article_data_list(months, search_filter)

        context = {"article_timeline_list": article_timeline_list}

        data = {
            "html": render(
                request,
                "main/includes/organisms/articles/articles_timeline_list.html",
                context,
            ).content.decode("utf-8"),
            "has_next": (
                len(self.get_base_shared_articles_query(search_filter)) != 0
                and (
                    self.materialize_shared_articles_query(
                        self.append_all_shared_articles_query(
                            MainArticlePage.objects.filter(search_filter)
                        )
                        .live()
                        .order_by("union_date")[:2]  # LIMIT 2
                    )[0]
                    not in article_timeline_list[-1]["articles"]
                )
            ),
        }

        return JsonResponse(data=data, safe=False)

    @route(r"^sdilene/$", name="shared")
    def shared(self, request):
        return self.setup_article_page_context(request)

    def serve(self, request, *args, **kwargs):
        if request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest":
            if "months" in request.GET:
                return self.get_timeline_articles_response(request)

        return super().serve(request, *args, **kwargs)

    @staticmethod
    def get_empty_month_data(date_obj):
        return {
            "month_number": date_obj.month,
            "month_text": MONTH_NAMES[date_obj.month - 1],
            "articles": [],
        }


class MainArticleTag(TaggedItemBase):
    content_object = ParentalKey(
        "main.MainArticlePage",
        on_delete=models.CASCADE,
        related_name="tagged_items",
    )


class MainArticlePage(
    ArticleMixin,
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
    PageInMenuMixin,
    Page,
):
    ### FIELDS
    content = StreamField(
        [
            (
                "text",
                RichTextBlock(template="main/includes/atoms/text/prose_richtext.html"),
            ),
            ("quote", blocks.ArticleQuoteBlock()),
            ("download", blocks.ArticleDownloadBlock()),
        ],
        verbose_name="Článek",
        blank=True,
        use_json_field=True,
    )

    author_page = models.ForeignKey(
        "main.MainPersonPage",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Stránka autora (osoby)",
    )
    tags = ClusterTaggableManager(
        through=MainArticleTag, related_name="tagged_articles", blank=True
    )
    shared_tags = ClusterTaggableManager(
        verbose_name="Tagy pro sdílení mezi weby",
        through=SharedTaggedMainArticle,
        blank=True,
    )

    search_fields = ArticleMixin.search_fields + [
        index.SearchField("author_page"),
        index.FilterField("slug"),
    ]

    ### PANELS

    content_panels = ArticleMixin.content_panels + [
        FieldPanel("author_page"),
        FieldPanel("tags"),
        FieldPanel("shared_tags"),
    ]

    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 = ["main.MainArticlesPage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Aktualita"

    # def get_context(self, request): chceme/nechceme?
    #     context = super().get_context(request)
    #     context["related_articles"] = (
    #         self.get_siblings(inclusive=False)
    #         .live()
    #         .specific()
    #         .order_by("-mainarticlepage__date")[:3]
    #     )
    #     return context


class MainProgramPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    ### FIELDS

    program = StreamField(
        [
            ("program_group", blocks.ProgramGroupBlock()),
            ("program_group_crossroad", blocks.ProgramGroupBlockCrossroad()),
            ("program_group_popout", blocks.ProgramGroupBlockPopout()),
        ],
        verbose_name="Program",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("program")]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        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",
    )

    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,
    )

    ### 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,
    SubpageMixin,
    MetadataPageMixin,
    CalendarMixin,
    PageInMenuMixin,
    Page,
):
    ### FIELDS
    main_image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="Hlavní obrázek",
        related_name="+",
    )

    profile_image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="Profilový obrázek",
        related_name="+",
    )
    before_name = models.CharField(
        "Tituly před jménem", max_length=32, blank=True, null=True
    )
    after_name = models.CharField(
        "Tituly za jménem", max_length=16, blank=True, null=True
    )
    position = models.CharField(
        "Pozice/povolání", max_length=200, blank=True, null=True
    )
    primary_group = models.CharField(
        "Kategorie",
        help_text="např. 'Europarlament' nebo 'Sněmovna'",
        max_length=32,
        blank=True,
        null=True,
    )
    perex = models.TextField()
    text = RichTextField()

    social_links = StreamField(
        [
            ("social_links", blocks.SocialLinkBlock()),
        ],
        verbose_name="Odkazy na sociální sítě",
        blank=True,
        use_json_field=True,
    )

    related_people = StreamField(
        [
            (
                "person",
                PageChooserBlock(page_type="main.MainPersonPage", label="Detail osoby"),
            )
        ],
        verbose_name="Další lidé",
        blank=True,
        use_json_field=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)

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainPeoplePage"]
    subpage_types = []

    ### PANELS
    content_panels = Page.content_panels + [
        FieldPanel("main_image"),
        FieldPanel("profile_image"),
        FieldPanel("before_name"),
        FieldPanel("after_name"),
        FieldPanel("position"),
        FieldPanel("perex"),
        FieldPanel("text"),
        FieldPanel("email"),
        FieldPanel("phone"),
        FieldPanel("calendar_url"),
        FieldPanel("social_links"),
        FieldPanel("related_people"),
    ]

    def get_context(self, request) -> dict:
        context = super().get_context(request)

        context["article_page_list"] = (
            MainArticlePage.objects.filter(author_page=self.id)
            .order_by("-date")
            .live()[:3]
        )

        return context

    ### OTHERS

    class Meta:
        verbose_name = "Detail osoby"
        # ordering = ("title",)

    def get_background_photo(self):
        """
        Vrací background_photo pro pozadí na stránce, pokud není nastaveno,
        vezme falbback z homepage
        """
        return (
            self.background_photo
            if self.background_photo
            else self.root_page.fallback_image
        )


class MainSimplePage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    ### FIELDS

    # content
    content = StreamField(
        [
            (
                "text",
                RichTextBlock(template="main/includes/atoms/text/prose_richtext.html"),
            ),
        ],
        verbose_name="Hlavní obsah",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("content")]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = [
        "main.MainHomePage",
        "main.MainSimplePage",
        "main.MainCrossroadPage",
        "main.MainPeoplePage",
    ]
    subpage_types = ["main.MainSimplePage"]

    ### OTHERS
    class Meta:
        verbose_name = "Jednoduchá stárnka"


class MainContactPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    ### FIELDS

    contact_people = StreamField(
        [("item", blocks.PersonContactBlock())],
        verbose_name="Kontaktní osoby",
        blank=True,
        use_json_field=True,
    )
    contact_boxes = StreamField(
        [("item", blocks.PersonContactBoxBlock())],
        verbose_name="Kontaktní boxy",
        blank=True,
        use_json_field=True,
    )
    text = StreamField(
        [("two_columns_text", blocks.TwoTextColumnBlock())],
        verbose_name="Kontaktní informace",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("text"),
        FieldPanel("contact_people"),
        FieldPanel("contact_boxes"),
    ]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Kontakty"


class MainCrossroadPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    ### FIELDS

    headlined_cards_content = StreamField(
        [(("headlined_cards"), blocks.CardLinkWithHeadlineBlock())],
        verbose_name="Karty rozcestníku s nadpisem",
        blank=True,
        use_json_field=True,
    )
    cards_content = StreamField(
        [("cards", blocks.CardLinkBlock())],
        verbose_name="Karty rozcestníku",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("headlined_cards_content"),
        FieldPanel("cards_content"),
    ]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = [
        "main.MainHomePage",
        "main.MainCrossroadPage",
    ]
    subpage_types = [
        "main.MainSimplePage",
        "main.MainCrossroadPage",
    ]
    ### OTHERS

    class Meta:
        verbose_name = "Rozcestník s kartami"


class MainHoaxPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    ### FIELDS

    description = RichTextField(
        "Popis",
        blank=True,
        null=True,
    )

    content = StreamField(
        [(("hoax"), blocks.HoaxBlock())],
        verbose_name="Hoaxy a jejich vysvětlení",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("description"),
        FieldPanel("content"),
    ]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = []
    ### OTHERS

    class Meta:
        verbose_name = "Hoaxy"


class MainSearchPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    parent_page_types = ["main.MainHomePage"]
    subpage_types = []

    class Meta:
        verbose_name = "Vyhledávací stránka"

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, args, kwargs)

        context["results"] = []

        if request.GET.get("q", "") == "":
            return context

        search_query = request.GET["q"]
        context["global_search_query"] = search_query

        for model in (
            MainPersonPage,
            MainArticlePage,
            MainSimplePage,
        ):
            filter = models.Q(title__icontains=search_query)

            if hasattr(model, "perex"):
                filter = filter | models.Q(perex__icontains=search_query)

            results = model.objects.filter(filter)

            if hasattr(model, "date"):
                results = results.order_by("-date")

            context["results"] += list(results.all()[:15])

        context["results"].sort(key=lambda result: result.title)

        return context