diff --git a/rca/guides/migrations/0029_accordion_streamfield_block.py b/rca/guides/migrations/0029_accordion_streamfield_block.py new file mode 100644 index 000000000..d8f61b920 --- /dev/null +++ b/rca/guides/migrations/0029_accordion_streamfield_block.py @@ -0,0 +1,261 @@ +# Generated by Django 4.2.11 on 2024-10-16 12:32 + +from django.db import migrations +import rca.navigation.models +import rca.utils.blocks.embeds +import wagtail.blocks +import wagtail.contrib.typed_table_block.blocks +import wagtail.embeds.blocks +import wagtail.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ("guides", "0027_link_block_url_label"), + ] + + operations = [ + migrations.AlterField( + model_name="guidepage", + name="body", + field=wagtail.fields.StreamField( + [ + ( + "anchor_heading", + wagtail.blocks.CharBlock( + form_classname="full title", + icon="title", + template="patterns/molecules/streamfield/blocks/anchor_heading_block.html", + ), + ), + ( + "heading", + wagtail.blocks.CharBlock( + form_classname="full title", + icon="title", + template="patterns/molecules/streamfield/blocks/heading_block.html", + ), + ), + ("paragraph", wagtail.blocks.RichTextBlock()), + ( + "image", + wagtail.blocks.StructBlock( + [ + ("image", wagtail.images.blocks.ImageChooserBlock()), + ("caption", wagtail.blocks.CharBlock(required=False)), + ( + "decorative", + wagtail.blocks.BooleanBlock( + help_text="Toggle to make image decorative so they can be ignored by assistive technologies.", + required=False, + ), + ), + ] + ), + ), + ( + "quote", + wagtail.blocks.StructBlock( + [ + ( + "quote", + wagtail.blocks.CharBlock( + form_classname="title", + help_text="Enter quote text only, there is no need to add quotation marks", + ), + ), + ("author", wagtail.blocks.CharBlock(required=False)), + ("job_title", wagtail.blocks.CharBlock(required=False)), + ] + ), + ), + ( + "embed", + wagtail.embeds.blocks.EmbedBlock( + help_text="Add a URL from these providers: YouTube, Vimeo, SoundCloud, Twitter.", + label="Embed media", + ), + ), + ( + "table", + wagtail.blocks.StructBlock( + [ + ( + "table", + wagtail.contrib.typed_table_block.blocks.TypedTableBlock( + [ + ( + "text", + wagtail.blocks.RichTextBlock( + features=["bold", "italic", "link"] + ), + ) + ] + ), + ), + ( + "first_row_is_header", + wagtail.blocks.BooleanBlock( + default=True, + label="The first row of columns are headers", + required=False, + ), + ), + ( + "first_col_is_header", + wagtail.blocks.BooleanBlock( + default=False, + label="The first column of each row is a header", + required=False, + ), + ), + ] + ), + ), + ( + "jw_video", + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + help_text="Optional title to identify the video. Not shown on the page.", + required=False, + ), + ), + ( + "video_url", + wagtail.blocks.URLBlock( + help_text="The URL of the video to show.", + max_length=1000, + ), + ), + ( + "poster_image", + wagtail.images.blocks.ImageChooserBlock( + help_text="The poster image to show as a placeholder for the video. For best results use an image 1920x1080 pixels" + ), + ), + ] + ), + ), + ( + "vepple_panorama", + wagtail.blocks.StructBlock( + [ + ( + "post_id", + wagtail.blocks.IntegerBlock( + help_text='NOTE: This is the number from the post="X" part of the embed code provided by Vepple. Wagtail only needs this ID, and will generate the rest of the embed code for you.', + label="Post ID", + ), + ) + ] + ), + ), + ( + "cookie_snippet_block", + rca.utils.blocks.embeds.CookieSnippetBlock( + "utils.CookieButtonSnippet" + ), + ), + ( + "cta_link", + wagtail.blocks.StructBlock( + [ + ( + "url", + rca.navigation.models.URLOrRelativeURLBLock( + label="URL", required=False + ), + ), + ( + "page", + wagtail.blocks.PageChooserBlock(required=False), + ), + ( + "title", + wagtail.blocks.CharBlock( + help_text="Leave blank to use the page's own title, required if using a URL", + required=False, + ), + ), + ] + ), + ), + ( + "accordion", + wagtail.blocks.StructBlock( + [ + ("heading", wagtail.blocks.CharBlock()), + ( + "items", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "heading", + wagtail.blocks.CharBlock( + help_text="A large heading diplayed next to the block", + required=False, + ), + ), + ( + "preview_text", + wagtail.blocks.CharBlock( + help_text="The text to display when the accordion is collapsed", + required=False, + ), + ), + ( + "body", + wagtail.blocks.RichTextBlock( + features=[ + "h2", + "h3", + "bold", + "italic", + "image", + "embed", + "ul", + "ol", + "link", + ], + help_text="The content shown when the accordion expanded", + ), + ), + ( + "link", + wagtail.blocks.StructBlock( + [ + ( + "title", + wagtail.blocks.CharBlock( + required=False + ), + ), + ( + "url", + wagtail.blocks.URLBlock( + required=False + ), + ), + ], + help_text="An optional link to display below the expanded content", + required=False, + ), + ), + ] + ) + ), + ), + ] + ), + ), + ], + blank=True, + ), + ), + ] diff --git a/rca/project_styleguide/templates/patterns/molecules/accordion/accordion.html b/rca/project_styleguide/templates/patterns/molecules/accordion/accordion.html index ff0421f59..5c806ee8c 100644 --- a/rca/project_styleguide/templates/patterns/molecules/accordion/accordion.html +++ b/rca/project_styleguide/templates/patterns/molecules/accordion/accordion.html @@ -42,11 +42,11 @@ {% endif %} {{ accordion.body|richtext|linebreaks }} {% if accordion.link.url and accordion.link.title %} - {% include "patterns/atoms/link-primary/link-primary--link.html" with href=accordion.link.url text=accordion.link.title %} + {% include "patterns/atoms/link-primary/link-primary--link.html" with href=accordion.link.url text=accordion.link.title %} {% endif %} {# Accordion can also use a snippet which has different link fields #} {% if accordion.link_url and accordion.link_title %} - {% include "patterns/atoms/link-primary/link-primary--link.html" with href=accordion.link_url text=accordion.link_title %} + {% include "patterns/atoms/link-primary/link-primary--link.html" with href=accordion.link_url text=accordion.link_title %} {% endif %} {% if scholarship %} {# Scholarship fields #} diff --git a/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/accordion_block.html b/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/accordion_block.html new file mode 100644 index 000000000..4235efe32 --- /dev/null +++ b/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/accordion_block.html @@ -0,0 +1,12 @@ +
+

{{ value.heading }}

+ +
+ {% for item in value.items %} + {% include "patterns/molecules/accordion/accordion.html" with accordion=item %} + {% endfor %} +
+
+ + + diff --git a/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/accordion_block.yaml b/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/accordion_block.yaml new file mode 100644 index 000000000..540cc78a1 --- /dev/null +++ b/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/accordion_block.yaml @@ -0,0 +1,22 @@ +context: + value: + heading: Unpredictable Knowledge Expander + items: + - heading: Pixel Artistry + preview_text: Diving into a pixelated universe, reshaping the boundaries of digital canvases + body: The realm of creations defies conventional borders, blending ancient techniques with digital frontiers. Learners embark on quests of discovery, drawing essence from a spectrum of disciplines, intertwining cutting-edge practices with traditional roots across the expansive corridors of our academy. + link: + url: '#' + title: 'Explore the Pixels' + - heading: Culinary Magic + preview_text: Stirring the pot of traditional and futuristic culinary arts + body: Our gastronomic journey knows no bounds, melding the forgotten alchemy of ancient recipes with the science of tomorrow's flavors. Aspiring chefs and food architects unite under our banner, forging paths that dazzle taste buds and challenge the essence of dining, all within the nurturing grounds of our community. + link: + url: '#' + title: 'Uncover the Secrets' + - heading: Echoes of Music + preview_text: Composing the future, resonating through the echoes of time + body: Our musical odyssey is a tapestry of sounds, embracing the silent whispers of the past and the roaring anthems of tomorrow. Participants are the maestros of their journey, orchestrating harmonies that bridge worlds, encouraged by our collective to explore, innovate, and redefine the symphony of life. + link: + url: '#' + title: 'Orchestrate Your Journey' \ No newline at end of file diff --git a/rca/static_src/sass/components/_accordion-block.scss b/rca/static_src/sass/components/_accordion-block.scss index e3671010a..2ee455646 100644 --- a/rca/static_src/sass/components/_accordion-block.scss +++ b/rca/static_src/sass/components/_accordion-block.scss @@ -32,6 +32,15 @@ margin-top: 0; } + &--streamfield { + overflow: unset; + + // Currently, background will always be black when used as a streamfield + .link--primary { + color: $color--orange !important; + } + } + &__heading { grid-column: 1 / span 2; margin-bottom: $gutter; diff --git a/rca/utils/blocks/content.py b/rca/utils/blocks/content.py index 0a39e05d5..d76bbaf2a 100644 --- a/rca/utils/blocks/content.py +++ b/rca/utils/blocks/content.py @@ -22,6 +22,7 @@ "InfoBlock", "StepBlock", "AccordionBlockWithTitle", + "AccordionBlock", "CustomTeaserBlock", "RelatedPageListBlockPage", "RelatedPageListBlock", @@ -248,6 +249,15 @@ def clean(self, value): return result +class AccordionBlock(blocks.StructBlock): + heading = blocks.CharBlock() + items = blocks.ListBlock(AccordionBlockWithTitle()) + + class Meta: + icon = "list-ul" + template = "patterns/molecules/streamfield/blocks/accordion_block.html" + + class CustomTeaserBlock(blocks.StructBlock): title = blocks.CharBlock(required=False) meta = blocks.CharBlock( diff --git a/rca/utils/blocks/story.py b/rca/utils/blocks/story.py index 6f31cd8aa..42c54ca1f 100644 --- a/rca/utils/blocks/story.py +++ b/rca/utils/blocks/story.py @@ -2,7 +2,14 @@ from wagtail.embeds.blocks import EmbedBlock from wagtail.snippets.blocks import SnippetChooserBlock -from .content import CTALinkBlock, DocumentBlock, ImageBlock, QuoteBlock, TableBlock +from .content import ( + AccordionBlock, + CTALinkBlock, + DocumentBlock, + ImageBlock, + QuoteBlock, + TableBlock, +) from .embeds import CookieSnippetBlock, JWPLayerBlock, VepplePanoramaBlock __all__ = [ @@ -57,6 +64,7 @@ class GuideBlock(blocks.StreamBlock): vepple_panorama = VepplePanoramaBlock() cookie_snippet_block = CookieSnippetBlock("utils.CookieButtonSnippet") cta_link = CTALinkBlock() + accordion = AccordionBlock() class Meta: template = "patterns/molecules/streamfield/stream_block.html"