Skip to content
Snippets Groups Projects
models.py 27.62 KiB
import random

from captcha.fields import CaptchaField
from django.db import models
from django.utils.translation import gettext_lazy
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
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.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.contrib.table_block.blocks import TableBlock
from wagtail.fields import RichTextField, StreamField
from wagtail.images.blocks import ImageChooserBlock
from wagtail.models import Page
from wagtail.search import index
from wagtailmetadata.models import MetadataPageMixin

from calendar_utils.models import CalendarMixin
from shared.blocks import (
    AdvancedTextBlock,
    ChartBlock,
    GalleryBlock,
    HeadlineBlock,
    NewsletterSubscriptionBlock,
    PictureHeadlineBlock,
)
from shared.const import RICH_TEXT_DEFAULT_FEATURES
from shared.models import (
    ArticleMixin,
    ArticlesPageMixin,
    CalendarMixin,
    ExtendedMetadataPageMixin,
    MainHomePageMixin,
    MainMenuMixin,
    MainSearchPageMixin,
    PdfPageMixin,
    SharedTaggedUniwebArticle,
    SocialMixin,
    SubpageMixin,
)
from shared_legacy.blocks import FlipCardsBlock
from shared_legacy.models import FooterMixin as LegacyFooterMixin
from shared_legacy.utils import make_promote_panels, strip_all_html_tags, trim_to_length
from tuning import admin_help

from .blocks import AlignedTableBlock, PeopleGroupListBlock, PersonUrlBlock
from .constants import (
    ALIGN_CHOICES,
    ALIGN_CSS,
    ARTICLES_PER_LINE,
    ARTICLES_PER_PAGE,
    BLACK_ON_WHITE,
    CALENDAR_EVENTS_CHOICES,
    COLOR_CHOICES,
    COLOR_CSS,
    FUTURE,
    LEFT,
)


class ColorBlock(blocks.StructBlock):
    """
    Intended as parent class for blocks with color option.
    """

    color = blocks.ChoiceBlock(COLOR_CHOICES, label="barva", default=BLACK_ON_WHITE)

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        if "css_class" not in context:
            context["css_class"] = []
        context["css_class"] += COLOR_CSS[value["color"]]
        return context


class AlignBlock(blocks.StructBlock):
    """
    Intended as parent class for blocks with align option.
    """

    align = blocks.ChoiceBlock(ALIGN_CHOICES, label="zarovnání", default=LEFT)

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        if "css_class" not in context:
            context["css_class"] = []
        context["css_class"] += ALIGN_CSS[value["align"]]
        return context


class ColumnsTextBlock(blocks.StructBlock):
    left_text = blocks.RichTextBlock(
        label="levý sloupec", features=RICH_TEXT_DEFAULT_FEATURES
    )
    right_text = blocks.RichTextBlock(
        label="pravý sloupec", features=RICH_TEXT_DEFAULT_FEATURES
    )

    class Meta:
        label = "text dva sloupce"
        icon = "doc-full"
        group = "texty"
        template = "uniweb/blocks/text_columns.html"


class AdvancedColumnsTextBlock(ColorBlock, AlignBlock):
    left_text = blocks.RichTextBlock(
        label="levý sloupec", features=RICH_TEXT_DEFAULT_FEATURES
    )
    right_text = blocks.RichTextBlock(
        label="pravý sloupec", features=RICH_TEXT_DEFAULT_FEATURES
    )

    class Meta:
        label = "text dva sloupce (pokročilý)"
        icon = "doc-full"
        group = "texty"
        template = "uniweb/blocks/advanced_text_columns.html"


class AdvancedTitleBlock(ColorBlock, AlignBlock):
    title = blocks.CharBlock(label="nadpis")

    class Meta:
        label = "nadpis (pokročilý)"
        icon = "title"
        group = "nadpisy"
        template = "uniweb/blocks/advanced_title.html"


class PictureListBlock(ColorBlock):
    items = blocks.ListBlock(
        blocks.RichTextBlock(label="odstavec", features=RICH_TEXT_DEFAULT_FEATURES),
        label="odstavce",
    )
    picture = ImageChooserBlock(
        label="obrázek",
        # TODO rozměry v helpu
        help_text="rozměr 25x25px nebo více (obrázek bude zmenšen na 25x25px)",
    )

    class Meta:
        label = "seznam z obrázkovými odrážkami"
        icon = "list-ul"
        group = "texty"
        template = "uniweb/blocks/picture_list.html"


class ArticlesBlock(blocks.StructBlock):
    page = blocks.PageChooserBlock(
        label="sekce článků", page_type=["uniweb.UniwebArticlesIndexPage"]
    )
    lines = blocks.IntegerBlock(
        label="počet řádků",
        default=1,
        help_text="zobrazí se tři články na řádek",
    )

    class Meta:
        label = "články"
        icon = "folder-open-1"
        group = "ostatní"
        template = "uniweb/blocks/articles.html"

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        count = value["lines"] * ARTICLES_PER_LINE
        articles_page = value["page"]
        context["articles"] = articles_page.materialize_shared_articles_query(
            articles_page.append_all_shared_articles_query(
                UniwebArticlePage.objects.child_of(articles_page)
            )[:count]
        )
        return context


class MenuItemBlock(blocks.StructBlock):
    name = blocks.CharBlock(label="název")
    page = blocks.PageChooserBlock(
        label="stránka",
        page_type=[
            "uniweb.UniwebHomePage",
            "uniweb.UniwebFlexiblePage",
            "uniweb.UniwebArticlesIndexPage",
            "uniweb.UniwebFormPage",
            "uniweb.UniwebPeoplePage",
            "uniweb.UniwebPersonPage",
            "uniweb.UniwebPdfPage",
            "district.DistrictPersonPage",
        ],
    )

    class Meta:
        label = "stránka"


class CalendarAgendaBlock(blocks.StructBlock):
    info = blocks.StaticBlock(
        label="volba kalendáře",
        admin_text="adresa kalendáře se zadává v nastavení hlavní stránky webu",
    )
    count = blocks.IntegerBlock(label="maximum událostí k zobrazení", default=10)

    event_type = blocks.ChoiceBlock(
        CALENDAR_EVENTS_CHOICES,
        label="druh událostí",
        default=FUTURE,
    )

    class Meta:
        label = "kalendář agenda"
        icon = "date"
        group = "ostatní"
        template = "uniweb/blocks/calendar_agenda.html"

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        count = value["count"]
        page = context.get("page")

        if page and page.root_page.has_calendar:
            if value["event_type"] == FUTURE and page.root_page.calendar.future_events:
                context["events"] = page.root_page.calendar.future_events[:count]
            elif page.root_page.calendar.past_events:
                context["events"] = page.root_page.calendar.past_events[:count]
            else:
                context["events"] = []
        else:
            context["events"] = []

        return context


class ButtonBlock(blocks.StructBlock):
    text = blocks.CharBlock(label="Nadpis")

    url = blocks.URLBlock(
        label="Odkaz",
        help_text="Pokud je odkaz vyplněný, není nutno vyplňovat stránku.",
        required=False,
    )

    page = blocks.PageChooserBlock(
        label="Stránka",
        help_text="Pokud je stránka vyplněná, není nutno vyplňovat odkaz.",
        required=False,
    )

    class Meta:
        label = "Tlačítko"
        icon = "link-external"
        group = "ostatní"
        template = "uniweb/blocks/button.html"


CONTENT_STREAM_BLOCKS = [
    # title, advanced_title
    ("headline", HeadlineBlock()),
    # picture_title
    ("picture_title", PictureHeadlineBlock()),
    # text
    (
        "text",
        blocks.RichTextBlock(
            label="Textový editor",
            features=RICH_TEXT_DEFAULT_FEATURES,
            template="styleguide2/includes/atoms/text/prose_richtext.html",
        ),
    ),
    # advanced_text
    ("advanced_text", AdvancedTextBlock()),
    # text_columns
    ("text_columns", ColumnsTextBlock()),
    # advanced_text_columns
    # gallery
    ("new_gallery", GalleryBlock()),
    # picture_list
    # aligned_table
    (
        "aligned_table",
        AlignedTableBlock(
            group="ostatní",
            template="styleguide2/includes/atoms/table/aligned_table.html",
        ),
    ),
    # table
    (
        "table",
        TableBlock(
            label="Tabulka",
            group="ostatní",
            template="styleguide2/includes/atoms/table/table.html",
        ),
    ),
    # articles
    # calendar_agenda
    # button
    # chart
    ("chart", ChartBlock()),
    # cards
    (
        "title",
        blocks.CharBlock(
            label="nadpis",
            icon="title",
            group="nadpisy",
            template="uniweb/blocks/title.html",
        ),
    ),
    ("advanced_title", AdvancedTitleBlock()),
    # (
    #     "text",
    #     blocks.RichTextBlock(
    #         label="Textový editor",
    #         features=RICH_TEXT_DEFAULT_FEATURES,
    #         template="styleguide2/includes/atoms/text/prose_richtext.html",
    #     ),
    # ),
    ("advanced_text_columns", AdvancedColumnsTextBlock()),
    (
        "gallery",
        blocks.ListBlock(
            ImageChooserBlock(label="obrázek"),
            label="galerie",
            icon="image",
            group="ostatní",
            template="uniweb/blocks/gallery.html",
        ),
    ),
    ("picture_list", PictureListBlock()),
    ("articles", ArticlesBlock()),
    ("calendar_agenda", CalendarAgendaBlock()),
    ("button", ButtonBlock()),
    ("cards", FlipCardsBlock(template="uniweb/blocks/flip_cards.html")),
]


class UniwebArticleTag(TaggedItemBase):
    content_object = ParentalKey(
        "uniweb.UniwebArticlePage",
        on_delete=models.CASCADE,
        related_name="tagged_items",
    )


class UniwebHomePage(CalendarMixin, LegacyFooterMixin, MainHomePageMixin):
    ### FIELDS

    fallback_image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        related_name="+",
        verbose_name="Obrázek pro pozadí stránek",
        help_text="Tento obrázek bude využit např. jako pozadí pro osobní stránky.",
    )

    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())],
        verbose_name="obsah stránky",
        blank=True,
        use_json_field=True,
    )

    # settings
    matomo_id = models.IntegerField(
        "Matomo ID pro sledování návštěvnosti",
        blank=True,
        null=True,
    )
    logo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="Logo pro web",
        help_text="Pokud žádné nezadáte, použije se default logo pirátů",
        related_name="uniweb_logo_image",
    )
    top_menu = StreamField(
        [("item", MenuItemBlock())],
        verbose_name="horní menu",
        blank=True,
        use_json_field=True,
    )
    narrow_layout = models.BooleanField(
        "zúžený obsah stránky",
        default=False,
        help_text="užší stránka je vhodná pro lepší čitelnost textů",
    )

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

    ### Footer
    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="Zobrazit logo"
    )
    show_social_links = models.BooleanField(
        "zobrazit soc. linky", default=True, help_text="Zobrazit link na sociální sítě"
    )
    show_pirate_buttons = models.BooleanField(
        "zobrazit pirátská tlačítka",
        default=True,
        help_text="Zobrazit pirátská tlačítka",
    )
    footer_extra_content = RichTextField(
        verbose_name="Extra obsah pod šedou patičkou",
        blank=True,
        features=RICH_TEXT_DEFAULT_FEATURES,
    )
    donation_page = models.URLField(
        "URL pro příjem darů (tlačítko Darovat)",
        blank=True,
        null=True,
        default="https://dary.pirati.cz",
    )

    ### PANELS

    settings_panels = [
        FieldPanel("logo"),
        MultiFieldPanel(
            [
                FieldPanel("matomo_id"),
                FieldPanel("title_suffix"),
                FieldPanel("narrow_layout"),
                FieldPanel("fallback_image"),
            ],
            "Obecné nastavení webu",
        ),
        MultiFieldPanel(
            [
                FieldPanel("calendar_url"),
                PageChooserPanel("calendar_page"),
            ],
            "Kalendář",
        ),
        MultiFieldPanel(
            [
                FieldPanel("hide_footer"),
                FieldPanel("show_logo"),
                FieldPanel("show_social_links"),
                FieldPanel("show_pirate_buttons"),
                FieldPanel("donation_page"),
            ],
            "Patička",
        ),
    ]

    menu_panels = (
        MainMenuMixin.menu_panels
        + SocialMixin.menu_panels
        + [
            FieldPanel("menu_button_name"),
            FieldPanel("menu_button_content"),
        ]
    )

    edit_handler = TabbedInterface(
        [
            ObjectList(MainHomePageMixin.content_panels, heading="Obsah"),
            ObjectList(menu_panels, heading="Hlavička"),
            ObjectList(MainHomePageMixin.footer_panels, heading="Patička"),
            ObjectList(MainHomePageMixin.promote_panels, heading="Propagace"),
            ObjectList(settings_panels, heading="Nastavení"),
        ]
    )

    ### 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 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(
    Page,
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
):
    ### FIELDS

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

    settings_panels = []

    ### 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(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(
    RoutablePageMixin,
    Page,
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
    ArticlesPageMixin,
):
    ### FIELDS

    ### PANELS

    content_panels = ArticlesPageMixin.content_panels

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["uniweb.UniwebHomePage"]
    subpage_types = ["uniweb.UniwebArticlePage"]

    ### OTHERS

    class Meta:
        verbose_name = "Sekce článků"

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

    def get_context(self, request):
        context = super().get_context(request)
        num = request.GET.get("page", 1)
        tag = request.GET.get("tag")

        tag_params = self.filter_by_tag_name(tag)

        own_children = UniwebArticlePage.objects.child_of(self)

        articles = self.append_all_shared_articles_query(
            own_children if tag is None else own_children.filter(**tag_params),
            custom_article_query=lambda articles: articles.filter(**tag_params)
            if tag is not None
            else articles,
        )

        context["articles"] = self.get_page_with_shared_articles(
            articles,
            ARTICLES_PER_PAGE,
            num,
        )
        context["tags"] = self.search_tags_by_unioned_id_query(articles)
        context["active_tag"] = tag
        return context


class UniwebArticlePage(
    ArticleMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
):
    ### FIELDS

    tags = ClusterTaggableManager(through=UniwebArticleTag, blank=True)
    shared_tags = ClusterTaggableManager(
        verbose_name="Tagy pro sdílení mezi weby",
        through=SharedTaggedUniwebArticle,
        blank=True,
    )

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

    ### PANELS

    content_panels = ArticleMixin.content_panels + [
        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 = ["uniweb.UniwebArticlesIndexPage"]
    subpage_types = ["uniweb.UniwebPdfPage"]

    ### OTHERS

    class Meta:
        verbose_name = "Článek"

    def get_context(self, request):
        context = super().get_context(request)
        context["related_articles"] = (
            (
                self.get_siblings(inclusive=False)
                .live()
                .specific()
                .order_by("-uniwebarticlepage__timestamp")[:3]
            )
            if self.shared_from is None
            else []
        )
        return context


class UniwebFormField(AbstractFormField):
    page = ParentalKey(
        "UniwebFormPage", on_delete=models.CASCADE, related_name="form_fields"
    )


class UniwebFormPage(
    AbstractForm, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
):
    ### FIELDS

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

    ### PANELS

    content_panels = AbstractForm.content_panels + [
        FieldPanel("content_before"),
        InlinePanel("form_fields", label="formulář"),
        FieldPanel("content_after"),
        FieldPanel("content_landing"),
    ]

    promote_panels = make_promote_panels()

    submissions_panels = [FormSubmissionsPanel()]

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading=gettext_lazy("Content")),
            ObjectList(promote_panels, heading=gettext_lazy("Promote")),
            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

    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


# Don't waste time making a new mixin for this,
# we'll be doing Octopus imports within a short while.
class UniwebPersonPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
):
    ### FIELDS
    job = models.CharField(
        "Povolání",
        max_length=128,
        blank=True,
        null=True,
        help_text="Např. 'Informatik'",
    )
    job_function = models.CharField(
        "Funkce", max_length=128, blank=True, null=True, help_text="Např. 'Předseda'"
    )
    background_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        related_name="+",
        verbose_name="obrázek do záhlaví",
    )
    profile_photo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        related_name="+",
        verbose_name="profilová fotka",
    )
    text = RichTextField("text", blank=True, features=RICH_TEXT_DEFAULT_FEATURES)

    email = models.EmailField("Email", null=True, blank=True)
    show_email = models.BooleanField("Zobrazovat email na stránce?", default=True)
    phone = models.CharField("Telefon", max_length=16, blank=True, null=True)
    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",
    )

    facebook_url = models.URLField("Odkaz na Facebook", blank=True, null=True)
    instagram_url = models.URLField("Odkaz na Instagram", blank=True, null=True)
    twitter_url = models.URLField("Odkaz na Twitter", blank=True, null=True)
    youtube_url = models.URLField("Odkaz na Youtube kanál", blank=True, null=True)
    flickr_url = models.URLField("Odkaz na Flickr", blank=True, null=True)
    custom_web_url = models.URLField("Odkaz na vlastní web", blank=True, null=True)
    other_urls = StreamField(
        [("other_url", PersonUrlBlock())],
        verbose_name="Další odkaz",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                FieldPanel("job"),
                FieldPanel("job_function"),
            ],
            "Základní údaje",
        ),
        MultiFieldPanel(
            [
                FieldPanel("profile_photo"),
                FieldPanel("background_photo"),
            ],
            "Fotky",
        ),
        FieldPanel("text"),
        MultiFieldPanel(
            [
                FieldPanel("email"),
                FieldPanel("show_email"),
                FieldPanel("phone"),
                FieldPanel("city"),
                FieldPanel("age"),
                FieldPanel("is_pirate"),
                FieldPanel("other_party"),
                FieldPanel("other_party_logo"),
            ],
            "Kontaktní informace",
        ),
        MultiFieldPanel(
            [
                FieldPanel("facebook_url"),
                FieldPanel("instagram_url"),
                FieldPanel("twitter_url"),
                FieldPanel("youtube_url"),
                FieldPanel("flickr_url"),
                FieldPanel("custom_web_url"),
                FieldPanel("other_urls"),
            ],
            "Sociální sítě",
        ),
    ]

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["uniweb.UniwebPeoplePage"]
    subpage_types = []

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

    def get_job_description(self):
        """
        Vrací povolání + funkci, s čárkou mezi nima, pokud jsou obě definovaná, jinak vrátí jednu z nich
        """
        if self.job and self.job_function:
            return f"{self.job}, {self.job_function}"
        return self.job or self.job_function or ""

    def get_context(self, request):
        context = super().get_context(request)
        # Na strance detailu cloveka se vpravo zobrazuji 3 dalsi nahodne profily
        context["random_people"] = list(
            self.get_siblings(inclusive=False).live().specific()
        )
        random.shuffle(context["random_people"])
        context["random_people"] = context["random_people"][:3]
        return context

    def get_meta_image(self):
        return self.search_image or self.profile_photo

    def get_meta_description(self):
        if self.search_description:
            return self.search_description

        if self.text:
            return trim_to_length(strip_all_html_tags(self.text))

        return None


class UniwebPeoplePage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
):
    ### FIELDS

    content = StreamField(
        [
            (
                "text",
                blocks.RichTextBlock(
                    label="Textový editor", features=RICH_TEXT_DEFAULT_FEATURES
                ),
            ),
            ("people_group", PeopleGroupListBlock()),
        ],
        verbose_name="Obsah stránky",
        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 = ["uniweb.UniwebHomePage"]
    subpage_types = ["uniweb.UniwebPersonPage"]

    ### OTHERS

    class Meta:
        verbose_name = "Lidé"


class UniwebPdfPage(MetadataPageMixin, SubpageMixin, Page, PdfPageMixin):
    """
    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"]