diff --git a/allies/models.py b/allies/models.py index eda56683e..8fbf7116f 100644 --- a/allies/models.py +++ b/allies/models.py @@ -88,3 +88,5 @@ def ally_subject_list(self): FieldPanel('short_description'), FieldPanel('long_description'), ] + + parent_page_types = ['pages.HomePage'] diff --git a/pages/custom_blocks.py b/pages/custom_blocks.py index 57591677e..4b64c4b11 100644 --- a/pages/custom_blocks.py +++ b/pages/custom_blocks.py @@ -1,7 +1,7 @@ from django import forms from wagtail import blocks -from wagtail.blocks import FieldBlock, StructBlock +from wagtail.blocks import FieldBlock, StructBlock, StructValue from wagtail.images.blocks import ImageChooserBlock from wagtail.documents.blocks import DocumentChooserBlock @@ -15,27 +15,74 @@ def get_api_representation(self, value, context=None): class Meta: icon = 'doc-full' + +class LinkStructValue(StructValue): + def url(self): + if self['external']: + return self['external'] + elif self['internal']: + return self['internal'] + elif self['document']: + return build_document_url(self['document'].url) + else: + return None + + def text(self): + return self['text'] + + def link_aria_label(self): + return self['link_aria_label'] + + def __bool__(self): + return bool(self.url()) + +class LinkBlock(blocks.StreamBlock): + external = blocks.URLBlock(required=False) + internal = blocks.PageChooserBlock(required=False) + document = DocumentChooserBlock(required=False) + + class Meta: + icon = 'link' + max_num = 1 + +class CTAButtonBlock(blocks.StructBlock): + text = blocks.CharBlock(required=True) + link = LinkBlock(required=True) + link_aria_label = blocks.CharBlock(required=True) + + class Meta: + icon = 'placeholder' + label = "CTA Button" + value_class = LinkStructValue + class ImageFormatChoiceBlock(FieldBlock): field = forms.ChoiceField(required=False, choices=( ('left', 'Wrap left'), ('right', 'Wrap right'), ('mid', 'Mid width'), ('full', 'Full width'),)) + +class ImageStructValue(StructValue): + def image(self): + return build_image_url(self['image']) + + def alt_text(self): + return self['alt_text'] + + def alignment(self): + return self['alignment'] + + def cta(self): + return self['cta'] + # Use this block to return the path in the page API, does not support alt_text and alignment class APIImageBlock(StructBlock): image = ImageChooserBlock(required=False) alt_text = blocks.CharBlock(required=False) - link_url = blocks.URLBlock(required=False) - link_aria_label = blocks.CharBlock(required=False) alignment = ImageFormatChoiceBlock(required=False) - identifier = blocks.CharBlock(required=False, help_text="Used by the frontend for Google Analytics.") - - def get_api_representation(self, value, context=None): - try: - return ImageSerializer(context=context).to_representation(value) - except AttributeError: - return + cta = CTAButtonBlock(required=False, label="CTA") class Meta: icon = 'image' + value_class = ImageStructValue # TODO: deprecate this block and move to the APIImageBlock class APIImageChooserBlock(ImageChooserBlock): @@ -193,11 +240,8 @@ class HeroBlock(blocks.StructBlock): heading = blocks.CharBlock(required=True) sub_heading = blocks.CharBlock(required=False) description = APIRichTextBlock(required=False) - image = APIImageBlock(required=False) - primary_cta_text = blocks.CharBlock(required=False) - primary_cta_link = blocks.URLBlock(required=False) - secondary_cta_text = blocks.CharBlock(required=False) - secondary_cta_link = blocks.URLBlock(required=False) + image = blocks.ListBlock(APIImageBlock(required=False), max_num=1) + cta = blocks.ListBlock(CTAButtonBlock(required=False), max_num=2) class Meta: icon = 'pilcrow' @@ -210,8 +254,7 @@ class CardsBlock(blocks.StructBlock): style = blocks.ChoiceBlock(choices=STYLE_CHOICES, default='rounded') heading = blocks.CharBlock(required=True) description = APIRichTextBlock(required=True) - link = blocks.URLBlock(required=False) - cta = blocks.CharBlock(required=False) + cta = CTAButtonBlock(required=False) image = APIImageBlock(required=False) class Meta: @@ -233,3 +276,19 @@ class SectionBlock(blocks.StructBlock): class Meta: icon = 'cog' + +class PageBodyBlock(blocks.StreamBlock): + hero = HeroBlock(required=False) + cards = blocks.ListBlock(CardsBlock(required=False)) + section = SectionBlock(required=False) + paragraph = APIRichTextBlock(required=False) + html = blocks.RawHTMLBlock(required=False) + image = APIImageBlock(required=False) + + class Meta: + icon = 'doc-full' + label = 'Page body' + group = 'Custom blocks' + max_num = 1 + required = True + help_text = 'This block is required and should be used only once per page.' diff --git a/pages/migrations/0090_rename_page_layout_rootpage_layout_and_more.py b/pages/migrations/0090_rename_page_layout_rootpage_layout_and_more.py new file mode 100644 index 000000000..57d47b7d5 --- /dev/null +++ b/pages/migrations/0090_rename_page_layout_rootpage_layout_and_more.py @@ -0,0 +1,272 @@ +# Generated by Django 5.0.4 on 2024-06-28 19:48 + +import django.db.models.deletion +import pages.custom_blocks +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("pages", "0089_alter_rootpage_body"), + ("wagtailimages", "0025_alter_image_file_alter_rendition_file"), + ] + + operations = [ + migrations.RenameField( + model_name="rootpage", + old_name="page_layout", + new_name="layout", + ), + migrations.AddField( + model_name="rootpage", + name="promote_image", + field=models.ForeignKey( + null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="+", to="wagtailimages.image" + ), + ), + migrations.AlterField( + model_name="rootpage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "hero", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=True)), + ("sub_heading", wagtail.blocks.CharBlock(required=False)), + ("description", pages.custom_blocks.APIRichTextBlock(required=False)), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock(required=False)), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ("link", wagtail.blocks.URLBlock(required=True)), + ("link_aria_label", wagtail.blocks.CharBlock(required=True)), + ], + required=False, + ), + ), + ], + required=False, + ), + ), + ( + "cta", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ("link", wagtail.blocks.URLBlock(required=True)), + ("link_aria_label", wagtail.blocks.CharBlock(required=True)), + ], + required=False, + ) + ), + ), + ] + ), + ), + ( + "section", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=False)), + ( + "content", + wagtail.blocks.ListBlock( + wagtail.blocks.StreamBlock( + [ + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "style", + wagtail.blocks.ChoiceBlock( + choices=[ + ("rounded", "Rounded"), + ("square", "Square"), + ] + ), + ), + ("heading", wagtail.blocks.CharBlock(required=True)), + ( + "description", + pages.custom_blocks.APIRichTextBlock(required=True), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.URLBlock(required=True), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + required=False, + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + required=False + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.URLBlock( + required=True + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + required=False, + ), + ), + ], + required=False, + ), + ), + ], + required=False, + ) + ), + ), + ("paragraph", pages.custom_blocks.APIRichTextBlock(required=False)), + ("html", wagtail.blocks.RawHTMLBlock(required=False)), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock(required=False), + ), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.URLBlock(required=True), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + required=False, + ), + ), + ], + required=False, + ), + ), + ( + "faqs", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "question", + wagtail.blocks.RichTextBlock(required=True), + ), + ("slug", wagtail.blocks.CharBlock(required=True)), + ("answer", wagtail.blocks.RichTextBlock(required=True)), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=False, + ) + ), + ), + ], + required=True, + ) + ), + ), + ] + ), + ), + ("paragraph", pages.custom_blocks.APIRichTextBlock()), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock(required=False)), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ("link", wagtail.blocks.URLBlock(required=True)), + ("link_aria_label", wagtail.blocks.CharBlock(required=True)), + ], + required=False, + ), + ), + ] + ), + ), + ("html", wagtail.blocks.RawHTMLBlock()), + ], + use_json_field=True, + ), + ), + ] diff --git a/pages/migrations/0091_alter_rootpage_body.py b/pages/migrations/0091_alter_rootpage_body.py new file mode 100644 index 000000000..7a656d3d5 --- /dev/null +++ b/pages/migrations/0091_alter_rootpage_body.py @@ -0,0 +1,406 @@ +# Generated by Django 5.0.4 on 2024-06-28 19:58 + +import pages.custom_blocks +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("pages", "0090_rename_page_layout_rootpage_layout_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="rootpage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "hero", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=True)), + ("sub_heading", wagtail.blocks.CharBlock(required=False)), + ("description", pages.custom_blocks.APIRichTextBlock(required=False)), + ( + "image", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock(required=False)), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock(required=False), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock(required=False), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + name="Call to action", + required=False, + ), + ), + ], + required=False, + ), + max_num=1, + ), + ), + ( + "cta", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ("external", wagtail.blocks.URLBlock(required=False)), + ( + "internal", + wagtail.blocks.PageChooserBlock(required=False), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ("link_aria_label", wagtail.blocks.CharBlock(required=True)), + ], + required=False, + ), + max_num=2, + ), + ), + ] + ), + ), + ( + "section", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=False)), + ( + "content", + wagtail.blocks.ListBlock( + wagtail.blocks.StreamBlock( + [ + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "style", + wagtail.blocks.ChoiceBlock( + choices=[ + ("rounded", "Rounded"), + ("square", "Square"), + ] + ), + ), + ("heading", wagtail.blocks.CharBlock(required=True)), + ( + "description", + pages.custom_blocks.APIRichTextBlock(required=True), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + required=False, + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + required=False + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + required=False + ), + ), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + name="Call to action", + required=False, + ), + ), + ], + required=False, + ), + ), + ], + required=False, + ) + ), + ), + ("paragraph", pages.custom_blocks.APIRichTextBlock(required=False)), + ("html", wagtail.blocks.RawHTMLBlock(required=False)), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock(required=False), + ), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + name="Call to action", + required=False, + ), + ), + ], + required=False, + ), + ), + ( + "faqs", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "question", + wagtail.blocks.RichTextBlock(required=True), + ), + ("slug", wagtail.blocks.CharBlock(required=True)), + ("answer", wagtail.blocks.RichTextBlock(required=True)), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=False, + ) + ), + ), + ], + required=True, + ) + ), + ), + ] + ), + ), + ("paragraph", pages.custom_blocks.APIRichTextBlock()), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock(required=False)), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ("alignment", pages.custom_blocks.ImageFormatChoiceBlock(required=False)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ("external", wagtail.blocks.URLBlock(required=False)), + ("internal", wagtail.blocks.PageChooserBlock(required=False)), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ("link_aria_label", wagtail.blocks.CharBlock(required=True)), + ], + name="Call to action", + required=False, + ), + ), + ] + ), + ), + ("html", wagtail.blocks.RawHTMLBlock()), + ], + use_json_field=True, + ), + ), + ] diff --git a/pages/migrations/0092_rename_flexiblepage_flexpage_alter_rootpage_body.py b/pages/migrations/0092_rename_flexiblepage_flexpage_alter_rootpage_body.py new file mode 100644 index 000000000..edecad045 --- /dev/null +++ b/pages/migrations/0092_rename_flexiblepage_flexpage_alter_rootpage_body.py @@ -0,0 +1,594 @@ +# Generated by Django 5.0.4 on 2024-07-01 15:10 + +import pages.custom_blocks +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("pages", "0091_alter_rootpage_body"), + ] + + operations = [ + migrations.RenameModel( + old_name="FlexiblePage", + new_name="FlexPage", + ), + migrations.AlterField( + model_name="rootpage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "content", + wagtail.blocks.StreamBlock( + [ + ( + "hero", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=True)), + ("sub_heading", wagtail.blocks.CharBlock(required=False)), + ("description", pages.custom_blocks.APIRichTextBlock(required=False)), + ( + "image", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock(required=False), + ), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + max_num=1, + min_num=0, + ), + ), + ( + "cta", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock(required=False), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + required=False, + ), + max_num=2, + min_num=0, + ), + ), + ], + required=False, + ), + ), + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "style", + wagtail.blocks.ChoiceBlock( + choices=[("rounded", "Rounded"), ("square", "Square")] + ), + ), + ("heading", wagtail.blocks.CharBlock(required=True)), + ("description", pages.custom_blocks.APIRichTextBlock(required=True)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock(required=False), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + required=False, + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock(required=False), + ), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ], + required=False, + ) + ), + ), + ( + "section", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=False)), + ( + "content", + wagtail.blocks.ListBlock( + wagtail.blocks.StreamBlock( + [ + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "style", + wagtail.blocks.ChoiceBlock( + choices=[ + ("rounded", "Rounded"), + ("square", "Square"), + ] + ), + ), + ( + "heading", + wagtail.blocks.CharBlock(required=True), + ), + ( + "description", + pages.custom_blocks.APIRichTextBlock( + required=True + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + required=False, + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + required=False + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + required=False + ), + ), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ], + required=False, + ) + ), + ), + ( + "paragraph", + pages.custom_blocks.APIRichTextBlock(required=False), + ), + ("html", wagtail.blocks.RawHTMLBlock(required=False)), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + required=False + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock(required=False), + ), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ( + "faqs", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "question", + wagtail.blocks.RichTextBlock( + required=True + ), + ), + ( + "slug", + wagtail.blocks.CharBlock(required=True), + ), + ( + "answer", + wagtail.blocks.RichTextBlock( + required=True + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=False, + ) + ), + ), + ], + required=True, + ) + ), + ), + ], + required=False, + ), + ), + ("paragraph", pages.custom_blocks.APIRichTextBlock(required=False)), + ("html", wagtail.blocks.RawHTMLBlock(required=False)), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock(required=False)), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ("alignment", pages.custom_blocks.ImageFormatChoiceBlock(required=False)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock(required=False), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock(required=False), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ("link_aria_label", wagtail.blocks.CharBlock(required=True)), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ] + ), + ) + ], + use_json_field=True, + ), + ), + ] diff --git a/pages/migrations/0093_alter_rootpage_body.py b/pages/migrations/0093_alter_rootpage_body.py new file mode 100644 index 000000000..69fab335f --- /dev/null +++ b/pages/migrations/0093_alter_rootpage_body.py @@ -0,0 +1,588 @@ +# Generated by Django 5.0.4 on 2024-07-01 15:12 + +import pages.custom_blocks +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("pages", "0092_rename_flexiblepage_flexpage_alter_rootpage_body"), + ] + + operations = [ + migrations.AlterField( + model_name="rootpage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "content", + wagtail.blocks.StreamBlock( + [ + ( + "hero", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=True)), + ("sub_heading", wagtail.blocks.CharBlock(required=False)), + ("description", pages.custom_blocks.APIRichTextBlock(required=False)), + ( + "image", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock(required=False), + ), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + max_num=1, + ), + ), + ( + "cta", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock(required=False), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + required=False, + ), + max_num=2, + ), + ), + ], + required=False, + ), + ), + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "style", + wagtail.blocks.ChoiceBlock( + choices=[("rounded", "Rounded"), ("square", "Square")] + ), + ), + ("heading", wagtail.blocks.CharBlock(required=True)), + ("description", pages.custom_blocks.APIRichTextBlock(required=True)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock(required=False), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + required=False, + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock(required=False), + ), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock(required=True), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock(required=True), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ], + required=False, + ) + ), + ), + ( + "section", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock(required=False)), + ( + "content", + wagtail.blocks.ListBlock( + wagtail.blocks.StreamBlock( + [ + ( + "cards", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "style", + wagtail.blocks.ChoiceBlock( + choices=[ + ("rounded", "Rounded"), + ("square", "Square"), + ] + ), + ), + ( + "heading", + wagtail.blocks.CharBlock(required=True), + ), + ( + "description", + pages.custom_blocks.APIRichTextBlock( + required=True + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + required=False, + ), + ), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + required=False + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock( + required=False + ), + ), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ], + required=False, + ) + ), + ), + ( + "paragraph", + pages.custom_blocks.APIRichTextBlock(required=False), + ), + ("html", wagtail.blocks.RawHTMLBlock(required=False)), + ( + "image", + wagtail.blocks.StructBlock( + [ + ( + "image", + wagtail.images.blocks.ImageChooserBlock( + required=False + ), + ), + ( + "alt_text", + wagtail.blocks.CharBlock(required=False), + ), + ( + "alignment", + pages.custom_blocks.ImageFormatChoiceBlock( + required=False + ), + ), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.CharBlock( + required=True + ), + ), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock( + required=False + ), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock( + required=False + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ( + "link_aria_label", + wagtail.blocks.CharBlock( + required=True + ), + ), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ( + "faqs", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "question", + wagtail.blocks.RichTextBlock( + required=True + ), + ), + ( + "slug", + wagtail.blocks.CharBlock(required=True), + ), + ( + "answer", + wagtail.blocks.RichTextBlock( + required=True + ), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=False, + ) + ), + ), + ], + required=True, + ) + ), + ), + ], + required=False, + ), + ), + ("paragraph", pages.custom_blocks.APIRichTextBlock(required=False)), + ("html", wagtail.blocks.RawHTMLBlock(required=False)), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock(required=False)), + ("alt_text", wagtail.blocks.CharBlock(required=False)), + ("alignment", pages.custom_blocks.ImageFormatChoiceBlock(required=False)), + ( + "cta", + wagtail.blocks.StructBlock( + [ + ("text", wagtail.blocks.CharBlock(required=True)), + ( + "link", + wagtail.blocks.StreamBlock( + [ + ( + "external", + wagtail.blocks.URLBlock(required=False), + ), + ( + "internal", + wagtail.blocks.PageChooserBlock(required=False), + ), + ( + "document", + wagtail.documents.blocks.DocumentChooserBlock( + required=False + ), + ), + ], + required=True, + ), + ), + ("link_aria_label", wagtail.blocks.CharBlock(required=True)), + ], + label="CTA", + required=False, + ), + ), + ], + required=False, + ), + ), + ] + ), + ) + ], + use_json_field=True, + ), + ), + ] diff --git a/pages/models.py b/pages/models.py index 2ac492f85..c147b57a7 100644 --- a/pages/models.py +++ b/pages/models.py @@ -31,11 +31,7 @@ TestimonialBlock, \ AllyLogoBlock, \ AssignableBookBlock, \ - CardBlock, \ - SectionBlock, \ - HeroBlock, \ - APIRichTextBlock, \ - APIImageBlock + PageBodyBlock from .custom_fields import \ Group @@ -44,25 +40,22 @@ # we have one RootPage, which is the parent of all other pages # this is the only page that should be created at the top level of the page tree +# this should be the homepage class RootPage(Page): - page_layout = models.ForeignKey(snippets.PageLayout, on_delete=models.PROTECT) + layout = models.ForeignKey(snippets.PageLayout, on_delete=models.PROTECT) body = StreamField([ - ('hero', HeroBlock()), - ('section', SectionBlock()), - ('paragraph', APIRichTextBlock()), - ('image', APIImageBlock()), - ('html', blocks.RawHTMLBlock()), + ('content', PageBodyBlock()), ], use_json_field=True) promote_image = models.ForeignKey( 'wagtailimages.Image', null=True, - blank=True, + blank=False, on_delete=models.SET_NULL, related_name='+' ) api_fields = [ - APIField('page_layout'), + APIField('layout'), APIField('body'), APIField('slug'), APIField('seo_title'), @@ -70,8 +63,8 @@ class RootPage(Page): ] content_panels = [ - TitleFieldPanel('title', help_text="For internal use only. This title will not be displayed on the site."), - FieldPanel('page_layout'), + TitleFieldPanel('title', help_text="For CMS use only. This title will not be displayed on the site."), + FieldPanel('layout'), FieldPanel('body'), ] @@ -85,6 +78,7 @@ class RootPage(Page): template = 'page.html' max_count = 1 parent_page_types = ['wagtailcore.Page'] + subpage_types = ['pages.FlexPage'] def __str__(self): return self.path @@ -111,12 +105,12 @@ def get_sitemap_urls(self, request=None): } ] -# change the RootPage to update fields in FlexiblePage -class FlexiblePage(RootPage): +# subclass of RootPage with a few overrides for +class FlexPage(RootPage): parent_page_types = ['pages.RootPage'] def get_url_parts(self, *args, **kwargs): - url_parts = super(FlexiblePage, self).get_url_parts(*args, **kwargs) + url_parts = super(FlexPage, self).get_url_parts(*args, **kwargs) if url_parts is None: return None