浏览代码

Implement theming for BlockQuote via a nested StructBlock

Thibaud Colas 4 天之前
父节点
当前提交
7c19ba7f6a

+ 24 - 0
bakerydemo/base/blocks.py

@@ -81,6 +81,29 @@ class HeadingBlock(StructBlock):
         description = "A heading with level two, three, or four"
         description = "A heading with level two, three, or four"
 
 
 
 
+class ThemeSettingsBlock(StructBlock):
+    theme = ChoiceBlock(
+        choices=[
+            ("default", "Default"),
+            ("highlight", "Highlight"),
+        ],
+        required=False,
+        default="default",
+    )
+    text_size = ChoiceBlock(
+        choices=[
+            ("default", "Default"),
+            ("large", "Large"),
+        ],
+        required=False,
+        default="default",
+    )
+
+    class Meta:
+        icon = "cog"
+        label_format = "Theme: {theme}, Text size: {text_size}"
+
+
 class BlockQuote(StructBlock):
 class BlockQuote(StructBlock):
     """
     """
     Custom `StructBlock` that allows the user to attribute a quote to the author
     Custom `StructBlock` that allows the user to attribute a quote to the author
@@ -88,6 +111,7 @@ class BlockQuote(StructBlock):
 
 
     text = TextBlock()
     text = TextBlock()
     attribute_name = CharBlock(blank=True, required=False, label="e.g. Mary Berry")
     attribute_name = CharBlock(blank=True, required=False, label="e.g. Mary Berry")
+    settings = ThemeSettingsBlock(collapsed=True)
 
 
     class Meta:
     class Meta:
         icon = "openquote"
         icon = "openquote"

+ 448 - 0
bakerydemo/base/migrations/0026_alter_formpage_body_alter_gallerypage_body_and_more.py

@@ -0,0 +1,448 @@
+# Generated by Django 5.2.1 on 2025-07-28 19:37
+
+import wagtail.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("base", "0025_homepage_featured_help_text"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="formpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+            ),
+        ),
+        migrations.AlterField(
+            model_name="gallerypage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+                verbose_name="Page body",
+            ),
+        ),
+        migrations.AlterField(
+            model_name="homepage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+                verbose_name="Home content block",
+            ),
+        ),
+        migrations.AlterField(
+            model_name="standardpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+                verbose_name="Page body",
+            ),
+        ),
+    ]

+ 123 - 0
bakerydemo/blog/migrations/0008_alter_blogpage_body.py

@@ -0,0 +1,123 @@
+# Generated by Django 5.2.1 on 2025-07-28 19:37
+
+import wagtail.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("blog", "0007_alter_blogpage_body"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="blogpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+                verbose_name="Page body",
+            ),
+        ),
+    ]

+ 123 - 0
bakerydemo/breads/migrations/0009_alter_breadpage_body.py

@@ -0,0 +1,123 @@
+# Generated by Django 5.2.1 on 2025-07-28 19:37
+
+import wagtail.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("breads", "0008_alter_breadpage_body"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="breadpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+                verbose_name="Page body",
+            ),
+        ),
+    ]

+ 123 - 0
bakerydemo/locations/migrations/0008_alter_locationpage_body.py

@@ -0,0 +1,123 @@
+# Generated by Django 5.2.1 on 2025-07-28 19:37
+
+import wagtail.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("locations", "0007_alter_locationpage_body"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="locationpage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+                verbose_name="Page body",
+            ),
+        ),
+    ]

+ 343 - 0
bakerydemo/recipes/migrations/0004_alter_recipepage_backstory_alter_recipepage_body.py

@@ -0,0 +1,343 @@
+# Generated by Django 5.2.1 on 2025-07-28 19:37
+
+import wagtail.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("recipes", "0003_alter_recipepage_backstory_alter_recipepage_body"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="recipepage",
+            name="backstory",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("image_block", 6),
+                    ("block_quote", 12),
+                    ("embed_block", 13),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "description": "A rich text paragraph",
+                            "icon": "pilcrow",
+                            "preview_value": '\n            <h2>Our bread pledge</h2>\n            <p>As a bakery, <b>breads</b> have <i>always</i> been in our hearts.\n            <a href="https://en.wikipedia.org/wiki/Staple_food">Staple foods</a>\n            are essential for society, and – bread is the tastiest of all.\n            We love to transform batters and doughs into baked goods with a firm\n            dry crust and fluffy center.</p>\n            ',
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: (
+                        "wagtail.images.blocks.ImageChooserBlock",
+                        (),
+                        {"required": True},
+                    ),
+                    5: ("wagtail.blocks.CharBlock", (), {"required": False}),
+                    6: (
+                        "wagtail.blocks.StructBlock",
+                        [[("image", 4), ("caption", 5), ("attribution", 5)]],
+                        {},
+                    ),
+                    7: ("wagtail.blocks.TextBlock", (), {}),
+                    8: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    9: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    10: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    11: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 9), ("text_size", 10)]],
+                        {"collapsed": True},
+                    ),
+                    12: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 7), ("attribute_name", 8), ("settings", 11)]],
+                        {},
+                    ),
+                    13: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_template": "base/preview/static_embed_block.html",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                },
+                help_text="Use only a minimum number of headings and large blocks.",
+            ),
+        ),
+        migrations.AlterField(
+            model_name="recipepage",
+            name="body",
+            field=wagtail.fields.StreamField(
+                [
+                    ("heading_block", 2),
+                    ("paragraph_block", 3),
+                    ("block_quote", 9),
+                    ("table_block", 10),
+                    ("typed_table_block", 15),
+                    ("image_block", 16),
+                    ("embed_block", 17),
+                    ("ingredients_list", 19),
+                    ("steps_list", 22),
+                ],
+                blank=True,
+                block_lookup={
+                    0: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"form_classname": "title", "required": True},
+                    ),
+                    1: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "blank": True,
+                            "choices": [
+                                ("", "Select a header size"),
+                                ("h2", "H2"),
+                                ("h3", "H3"),
+                                ("h4", "H4"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    2: (
+                        "wagtail.blocks.StructBlock",
+                        [[("heading_text", 0), ("size", 1)]],
+                        {"group": "Content"},
+                    ),
+                    3: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {
+                            "group": "Content",
+                            "icon": "pilcrow",
+                            "template": "blocks/paragraph_block.html",
+                        },
+                    ),
+                    4: ("wagtail.blocks.TextBlock", (), {}),
+                    5: (
+                        "wagtail.blocks.CharBlock",
+                        (),
+                        {"blank": True, "label": "e.g. Mary Berry", "required": False},
+                    ),
+                    6: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [
+                                ("default", "Default"),
+                                ("highlight", "Highlight"),
+                            ],
+                            "required": False,
+                        },
+                    ),
+                    7: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {
+                            "choices": [("default", "Default"), ("large", "Large")],
+                            "required": False,
+                        },
+                    ),
+                    8: (
+                        "wagtail.blocks.StructBlock",
+                        [[("theme", 6), ("text_size", 7)]],
+                        {"collapsed": True},
+                    ),
+                    9: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 4), ("attribute_name", 5), ("settings", 8)]],
+                        {"group": "Content"},
+                    ),
+                    10: (
+                        "wagtail.contrib.table_block.blocks.TableBlock",
+                        (),
+                        {
+                            "description": "A table of data with plain text cells",
+                            "group": "Content",
+                            "preview_value": {
+                                "data": [
+                                    ["Bread type", "Origin"],
+                                    ["Anpan", "Japan"],
+                                    ["Crumpet", "United Kingdom"],
+                                    ["Roti buaya", "Indonesia"],
+                                ],
+                                "first_row_is_table_header": "True",
+                            },
+                        },
+                    ),
+                    11: ("wagtail.blocks.CharBlock", (), {}),
+                    12: ("wagtail.blocks.FloatBlock", (), {}),
+                    13: ("wagtail.blocks.RichTextBlock", (), {}),
+                    14: ("wagtail.images.blocks.ImageBlock", [], {}),
+                    15: (
+                        "wagtail.contrib.typed_table_block.blocks.TypedTableBlock",
+                        [
+                            [
+                                ("text", 11),
+                                ("numeric", 12),
+                                ("rich_text", 13),
+                                ("image", 14),
+                            ]
+                        ],
+                        {
+                            "description": "A table of data with cells that can include text, numbers, rich text, and images",
+                            "group": "Content",
+                            "preview_value": {
+                                "caption": "Nutritional information for 100g of bread",
+                                "columns": [
+                                    {"heading": "Nutrient", "type": "rich_text"},
+                                    {"heading": "White bread", "type": "numeric"},
+                                    {"heading": "Brown bread", "type": "numeric"},
+                                    {"heading": "Wholemeal bread", "type": "numeric"},
+                                ],
+                                "rows": [
+                                    {
+                                        "values": [
+                                            '<p><a href="https://en.wikipedia.org/wiki/Protein">Protein</a> <b>(g)</b></p>',
+                                            7.9,
+                                            7.9,
+                                            9.4,
+                                        ]
+                                    },
+                                    {
+                                        "values": [
+                                            '<p><a href="https://en.wikipedia.org/wiki/Carbohydrate">Carbohydrate</a> <b>(g)</b></p>',
+                                            46.1,
+                                            42.1,
+                                            42,
+                                        ]
+                                    },
+                                    {
+                                        "values": [
+                                            '<p><a href="https://en.wikipedia.org/wiki/Sugar">Total sugars</a> <b>(g)</b></p>',
+                                            3.4,
+                                            3.4,
+                                            2.8,
+                                        ]
+                                    },
+                                ],
+                            },
+                        },
+                    ),
+                    16: ("wagtail.images.blocks.ImageBlock", [], {"group": "Media"}),
+                    17: (
+                        "wagtail.embeds.blocks.EmbedBlock",
+                        (),
+                        {
+                            "description": "An embedded video or other media",
+                            "group": "Media",
+                            "help_text": "Insert an embed URL e.g https://www.youtube.com/watch?v=SGJFWirQ3ks",
+                            "icon": "media",
+                            "preview_value": "https://www.youtube.com/watch?v=mwrGSfiB1Mg",
+                            "template": "blocks/embed_block.html",
+                        },
+                    ),
+                    18: (
+                        "wagtail.blocks.RichTextBlock",
+                        (),
+                        {"features": ["bold", "italic", "link"]},
+                    ),
+                    19: (
+                        "wagtail.blocks.ListBlock",
+                        (18,),
+                        {
+                            "description": "A list of ingredients to use in the recipe with optional bold, italic, and link options",
+                            "group": "Cooking",
+                            "icon": "list-ol",
+                            "max_num": 10,
+                            "min_num": 2,
+                            "preview_value": [
+                                "<p>200g flour</p>",
+                                "<p>1 egg</p>",
+                                "<p>1 cup of sugar</p>",
+                            ],
+                        },
+                    ),
+                    20: (
+                        "wagtail.blocks.ChoiceBlock",
+                        [],
+                        {"choices": [("S", "Small"), ("M", "Medium"), ("L", "Large")]},
+                    ),
+                    21: (
+                        "wagtail.blocks.StructBlock",
+                        [[("text", 18), ("difficulty", 20)]],
+                        {},
+                    ),
+                    22: (
+                        "wagtail.blocks.ListBlock",
+                        (21,),
+                        {
+                            "description": "A list of steps to follow in the recipe, with a difficulty rating for each step",
+                            "group": "Cooking",
+                            "icon": "tasks",
+                            "max_num": 10,
+                            "min_num": 2,
+                            "preview_value": [
+                                {"difficulty": "S", "text": "<p>An easy step</p>"},
+                                {"difficulty": "L", "text": "<p>A difficult step</p>"},
+                                {"difficulty": "M", "text": "<p>A medium step</p>"},
+                            ],
+                        },
+                    ),
+                },
+                help_text="The recipe’s step-by-step instructions and any other relevant information.",
+            ),
+        ),
+    ]

+ 23 - 26
bakerydemo/static/css/main.css

@@ -366,38 +366,35 @@ caption {
   }
   }
 }
 }
 
 
-blockquote {
+.blockquote {
   border-left: 3px solid var(--orange);
   border-left: 3px solid var(--orange);
-  margin: 40px 0 30px;
-  padding: 0 0 0 20px;
-}
-
-blockquote .text {
+  padding: 30px 0 10px 20px;
   color: var(--orange);
   color: var(--orange);
-  margin: 0 0 30px;
-  font-family: var(--font--primary);
-  font-size: 1.625rem;
-  line-height: 1.15;
-}
 
 
-blockquote .attribute-name {
-  color: var(--dark);
-  font-size: var(--font-md);
-  line-height: 1.56;
-  margin: 0;
-  padding: 0;
-}
+  .text {
+    color: inherit;
+    margin: 0 0 30px;
+    font-family: var(--font--primary);
+    font-size: 1.625rem;
+    line-height: 1.15;
+  }
 
 
-@media (min-width: 768px) {
-  blockquote {
-    border-left: 3px solid var(--orange);
-    margin: 50px 0;
-    padding: 0 40px;
+  .attribute-name {
+    color: var(--dark);
+    font-size: var(--font-md);
   }
   }
 
 
-  blockquote .text {
-    font-size: 2rem;
-    line-height: 1.31;
+  &.blockquote--highlight {
+    background-color: var(--dark);
+    color: var(--cream);
+
+    .attribute-name {
+      color: var(--white);
+    }
+  }
+
+  &.blockquote--text-large .text {
+    font-size: 2.875rem;
   }
   }
 }
 }
 
 

+ 1 - 1
bakerydemo/templates/blocks/blockquote.html

@@ -1,5 +1,5 @@
 {% load wagtailimages_tags %}
 {% load wagtailimages_tags %}
 
 
-<blockquote><p class="text">{{ self.text }}</p>
+<blockquote class="blockquote blockquote--{{ self.settings.theme }} blockquote--text-{{ self.settings.text_size }}"><p class="text">{{ self.text }}</p>
     <p class="attribute-name">{{ self.attribute_name}}</p>
     <p class="attribute-name">{{ self.attribute_name}}</p>
 </blockquote>
 </blockquote>