Skip to content
Snippets Groups Projects
Select Git revision
  • 72e2fdd175a86cb59f2a3cef28118e2bafea2625
  • master default protected
  • 2.0.0-alpha-11
  • 2.0.0-alpha-10
  • 2.0.0-alpha-9
  • 2.0.0-alpha-8
  • 2.0.0-alpha-7
  • 2.0.0-alpha-6
  • 2.0.0-alpha-5
  • 2.0.0-alpha-4
  • 2.0.0-alpha-3
  • 2.0.0-alpha-2
  • 2.0.0-alpha-1
  • 1.8.0
  • 1.7.0
  • 1.6.4
  • 1.6.3
  • 1.6.2
  • 1.6.1
  • 1.6.0
  • 1.5.5
  • 1.5.4
22 results

tailwind.config.js

Blame
  • Forked from TO / Weby / ui-styleguide
    Source project has a limited visibility.
    models.py 22.54 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.models import Page
    from wagtail.search import index
    from wagtailmetadata.models import MetadataPageMixin
    
    from calendar_utils.models import CalendarMixin
    from shared.blocks import (
        DEFAULT_CONTENT_BLOCKS,
        AdvancedColumnsTextBlock,
        AdvancedTextBlock,
    )
    from shared.blocks import ButtonBlock as SharedButtonBlock
    from shared.blocks import (
        ChartBlock,
        ColumnsTextBlock,
        FlipCardsBlock,
        GalleryBlock,
        HeadlineBlock,
        NewsletterSubscriptionBlock,
        PictureHeadlineBlock,
        PictureListBlock,
    )
    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.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 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"
            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
    
    
    CONTENT_STREAM_BLOCKS = DEFAULT_CONTENT_BLOCKS + [
        ("calendar_agenda", CalendarAgendaBlock())
    ]
    
    
    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"]