diff --git a/uniweb/blocks.py b/uniweb/blocks.py new file mode 100644 index 0000000000000000000000000000000000000000..1aaf9c48bca5524a4594ef6f237a453fb736c356 --- /dev/null +++ b/uniweb/blocks.py @@ -0,0 +1,42 @@ +from wagtail.blocks import ( + CharBlock, + ListBlock, + PageChooserBlock, + StructBlock, + URLBlock, +) + + +class PersonUrlBlock(StructBlock): + title = CharBlock(label="Název", required=True) + url = URLBlock(label="URL", required=True) + custom_icon = CharBlock( + label="Vlastní ikonka ze styleguide", + required=False, + help_text="Pro vlastní ikonku zadejde název ikonky z https://styleguide.pirati.cz/latest/?p=viewall-atoms-icons (bez tečky), např. 'ico--beer'", + ) + + +class PersonCustomPositionBlock(StructBlock): + position = CharBlock(label="Název pozice", required=False) + person = PageChooserBlock( + label="Osoba", + page_type=["uniweb.UniwebPersonPage"], + ) + + class Meta: + icon = "user" + label = "Osoba s volitelnou pozicí" + + +class PeopleGroupListBlock(StructBlock): + group_title = CharBlock(label="Titulek", required=True) + person_list = ListBlock( + PersonCustomPositionBlock(), + label="List osob", + ) + + class Meta: + template = "uniweb/blocks/people_group_block.html" + icon = "list-ul" + label = "Skupina členů" diff --git a/uniweb/migrations/0038_uniwebpersonpage_uniwebpeoplepage.py b/uniweb/migrations/0038_uniwebpersonpage_uniwebpeoplepage.py new file mode 100644 index 0000000000000000000000000000000000000000..aa8762745cfffa846f5ba15f7324f107056ee32d --- /dev/null +++ b/uniweb/migrations/0038_uniwebpersonpage_uniwebpeoplepage.py @@ -0,0 +1,64 @@ +# Generated by Django 4.1.6 on 2023-03-09 23:46 + +from django.db import migrations, models +import django.db.models.deletion +import shared.models +import wagtail.blocks +import wagtail.fields +import wagtailmetadata.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wagtailcore', '0083_workflowcontenttype'), + ('wagtailimages', '0025_alter_image_file_alter_rendition_file'), + ('uniweb', '0037_alter_uniwebflexiblepage_content_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='UniwebPersonPage', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('job', models.CharField(blank=True, help_text="Např. 'Informatik'", max_length=128, null=True, verbose_name='Povolání')), + ('job_function', models.CharField(blank=True, help_text="Např. 'Předseda'", max_length=128, null=True, verbose_name='Funkce')), + ('text', wagtail.fields.RichTextField(blank=True, verbose_name='text')), + ('email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='Email')), + ('show_email', models.BooleanField(default=True, verbose_name='Zobrazovat email na stránce?')), + ('phone', models.CharField(blank=True, max_length=16, null=True, verbose_name='Telefon')), + ('city', models.CharField(blank=True, max_length=64, null=True, verbose_name='Město/obec')), + ('age', models.IntegerField(blank=True, null=True, verbose_name='Věk')), + ('is_pirate', models.BooleanField(default=True, verbose_name='Je členem Pirátské strany?')), + ('other_party', models.CharField(blank=True, help_text='Vyplňte pokud osoba není Pirát', max_length=64, null=True, verbose_name='Strana')), + ('facebook_url', models.URLField(blank=True, null=True, verbose_name='Odkaz na Facebook')), + ('instagram_url', models.URLField(blank=True, null=True, verbose_name='Odkaz na Instagram')), + ('twitter_url', models.URLField(blank=True, null=True, verbose_name='Odkaz na Twitter')), + ('youtube_url', models.URLField(blank=True, null=True, verbose_name='Odkaz na Youtube kanál')), + ('flickr_url', models.URLField(blank=True, null=True, verbose_name='Odkaz na Flickr')), + ('custom_web_url', models.URLField(blank=True, null=True, verbose_name='Odkaz na vlastní web')), + ('other_urls', wagtail.fields.StreamField([('other_url', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Název', required=True)), ('url', wagtail.blocks.URLBlock(label='URL', required=True)), ('custom_icon', wagtail.blocks.CharBlock(help_text="Pro vlastní ikonku zadejde název ikonky z https://styleguide.pirati.cz/latest/?p=viewall-atoms-icons (bez tečky), např. 'ico--beer'", label='Vlastní ikonka ze styleguide', required=False))]))], blank=True, use_json_field=True, verbose_name='Další odkaz')), + ('background_photo', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtailimages.image', verbose_name='obrázek do záhlaví')), + ('other_party_logo', models.ForeignKey(blank=True, help_text='Vyplňte pokud osoba není Pirát', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtailimages.image', verbose_name='Logo strany')), + ('profile_photo', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='wagtailimages.image', verbose_name='profilová fotka')), + ('search_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Search image')), + ], + options={ + 'verbose_name': 'Detail osoby', + 'ordering': ('title',), + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + migrations.CreateModel( + name='UniwebPeoplePage', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('content', wagtail.fields.StreamField([('text', wagtail.blocks.RichTextBlock(features=['h2', 'h3', 'h4', 'h5', 'bold', 'italic', 'ol', 'ul', 'hr', 'link', 'document-link', 'image', 'superscript', 'subscript', 'strikethrough', 'blockquote', 'embed'], label='Textový editor')), ('people_group', wagtail.blocks.StructBlock([('group_title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('person_list', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('position', wagtail.blocks.CharBlock(label='Název pozice', required=False)), ('person', wagtail.blocks.PageChooserBlock(label='Osoba', page_type=['uniweb.UniwebPersonPage']))]), label='List osob'))]))], blank=True, use_json_field=True, verbose_name='Obsah stránky')), + ('search_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.image', verbose_name='Search image')), + ], + options={ + 'verbose_name': 'Lidé', + }, + bases=(shared.models.SubpageMixin, wagtailmetadata.models.WagtailImageMetadataMixin, 'wagtailcore.page', models.Model), + ), + ] diff --git a/uniweb/models.py b/uniweb/models.py index e6b613cf50ee0eddeaf417428af235fa41ef0cf4..947ffc2e9f66d65c9a4915c97373d1e337152b18 100644 --- a/uniweb/models.py +++ b/uniweb/models.py @@ -17,13 +17,14 @@ from wagtail.admin.panels import ( from wagtail.contrib.forms.models import AbstractForm, AbstractFormField from wagtail.contrib.forms.panels import FormSubmissionsPanel from wagtail.contrib.table_block.blocks import TableBlock -from wagtail.fields import StreamField +from wagtail.fields import RichTextField, StreamField from wagtail.images.blocks import ImageChooserBlock from wagtail.models import Page from wagtailmetadata.models import MetadataPageMixin from calendar_utils.models import CalendarMixin from shared.blocks import ChartBlock +from shared.const import RICH_TEXT_DEFAULT_FEATURES from shared.models import ( ArticleMixin, ExtendedMetadataHomePageMixin, @@ -33,6 +34,11 @@ from shared.models import ( from shared.utils import make_promote_panels from tuning import admin_help +from .blocks import ( + PersonCustomPositionBlock, + PeopleGroupListBlock, + PersonUrlBlock, +) from .constants import ( ALIGN_CHOICES, ALIGN_CSS, @@ -580,3 +586,204 @@ class UniwebFormPage( 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_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é"