Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions bedrock/mozorg/blocks/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,6 @@ class SpringboardItemBlock(blocks.StructBlock):
("Podcast", "Podcast"),
("Video", "Video"),
],
help_text="Selects a visual icon type for the link.",
)

icon = blocks.ChoiceBlock(
required=False,
choices=[
("article", "Article"),
("podcast", "Podcast"),
("video", "Video"),
],
help_text="Selects an icon for the row.",
)

topic = blocks.ChoiceBlock(
Expand All @@ -89,14 +78,14 @@ class SpringboardItemBlock(blocks.StructBlock):
("Artificial Intelligence", "Artificial Intelligence"),
("Open Source AI", "Open Source AI"),
("Privacy & Security", "Privacy & Security"),
("Data", "Data"),
],
help_text="Selects a topic.",
)

author = blocks.CharBlock(
required=False,
char_max_length=255,
help_text="Author name(s), website name",
help_text="Author or website name(s)",
)

preview = blocks.CharBlock(
Expand All @@ -108,12 +97,13 @@ class SpringboardItemBlock(blocks.StructBlock):
url = blocks.URLBlock(
required=True,
char_max_length=255,
help_text="Link to the person's website or social media account with UTMs.",
help_text="Link to the full content.",
)

class Meta:
icon = "grip"
label = "Springboard Item"
label_format = "{preview}"


class SpringboardBlockSettings(blocks.StructBlock):
Expand Down
5 changes: 0 additions & 5 deletions bedrock/mozorg/fixtures/springboard_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ def get_springboard_variants() -> list[dict]:
{
"url": "https://example.com/article1",
"type": "Article",
"icon": "article",
"topic": "Privacy & Security",
"author": "Jane Doe",
"preview": "Understanding privacy in the digital age",
},
{
"url": "https://example.com/video1",
"type": "Video",
"icon": "video",
"topic": "Privacy & Security",
"author": "John Smith",
"preview": "How to secure your online accounts",
Expand All @@ -65,23 +63,20 @@ def get_springboard_variants() -> list[dict]:
{
"url": "https://example.com/podcast1",
"type": "Podcast",
"icon": "podcast",
"topic": "",
"author": "Mozilla Team",
"preview": "Latest tech trends discussion",
},
{
"url": "https://example.com/blog1",
"type": "Article",
"icon": "article",
"topic": "",
"author": "Alice Johnson",
"preview": "The future of open source software",
},
{
"url": "https://example.com/webinar1",
"type": "Video",
"icon": "video",
"topic": "",
"author": "Bob Williams",
"preview": "Teaching coding to beginners",
Expand Down
24 changes: 24 additions & 0 deletions bedrock/mozorg/migrations/0045_alter_homepage_content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

# Generated by Django 5.2.14 on 2026-08-04 18:59

import wagtail.admin.forms.choosers
import wagtail.fields
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('mozorg', '0044_delete_leadershippage_contentmodels'),
]

operations = [
migrations.AlterField(
model_name='homepage',
name='content',
field=wagtail.fields.StreamField([('springboard_block', 16), ('donate_block', 33), ('gallery_block', 46), ('showcase_block', 54), ('transition_block', 57)], blank=True, block_lookup={0: ('wagtail.blocks.CharBlock', (), {'help_text': "Optional: Add an ID to make this section linkable (e.g., 'media', 'support').", 'max_length': 100, 'required': False}), 1: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('', 'White'), ('m24-t-dark', 'Dark'), ('m24-t-green', 'Green'), ('m24-t-orange', 'Orange'), ('m24-t-pink', 'Pink'), ('m24-t-gray', 'Gray')], 'help_text': 'What color should the background be?', 'required': False}), 2: ('wagtail.blocks.StructBlock', [[('anchor_id', 0), ('background_color', 1)]], {}), 3: ('bedrock.mozorg.blocks.common.DividerBlock', (), {'label': 'Text'}), 4: ('wagtail.blocks.CharBlock', (), {'help_text': 'Use sentence case.', 'max_length': 255, 'required': False}), 5: ('wagtail.blocks.CharBlock', (), {'help_text': 'Column name, e.g.: Type', 'label': 'Title for column one', 'max_length': 255}), 6: ('wagtail.blocks.CharBlock', (), {'help_text': 'Column name, e.g.: Author(s)', 'label': 'Title for column two', 'max_length': 255}), 7: ('wagtail.blocks.CharBlock', (), {'help_text': 'Column name, e.g.: Topic', 'label': 'Title for column three', 'max_length': 255}), 8: ('wagtail.blocks.CharBlock', (), {'help_text': 'Column name, e.g.: Intro', 'label': 'Title for column four', 'max_length': 255}), 9: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('Article', 'Article'), ('Podcast', 'Podcast'), ('Video', 'Video')], 'required': False}), 10: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('News', 'News'), ('Products', 'Products'), ('Artificial Intelligence', 'Artificial Intelligence'), ('Open Source AI', 'Open Source AI'), ('Privacy & Security', 'Privacy & Security'), ('Data', 'Data')], 'required': False}), 11: ('wagtail.blocks.CharBlock', (), {'char_max_length': 255, 'help_text': 'Author or website name(s)', 'required': False}), 12: ('wagtail.blocks.CharBlock', (), {'char_max_length': 255, 'help_text': 'Short preview of the content', 'required': False}), 13: ('wagtail.blocks.URLBlock', (), {'char_max_length': 255, 'help_text': 'Link to the full content.', 'required': True}), 14: ('wagtail.blocks.StructBlock', [[('type', 9), ('topic', 10), ('author', 11), ('preview', 12), ('url', 13)]], {}), 15: ('wagtail.blocks.ListBlock', (14,), {'min_num': 1}), 16: ('wagtail.blocks.StructBlock', [[('settings', 2), ('text_divider', 3), ('heading', 4), ('column_one', 5), ('column_two', 6), ('column_three', 7), ('column_four', 8), ('springboard_items', 15)]], {}), 17: ('wagtail.blocks.CharBlock', (), {'help_text': 'Use sentence case.', 'max_length': 255}), 18: ('wagtail.blocks.RichTextBlock', (), {'features': ['bold', 'link'], 'help_text': 'Keep this to 2 paragraphs or fewer.'}), 19: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Ideal image size is 1400 x 700. Image will be cropped to a 2:1 aspect ratio.'}), 20: ('wagtail.blocks.CharBlock', (), {'help_text': "A concise description of the image for someone who can't see it. See <a href='https://mozmeao.github.io/platform-docs/cms/alt-text/' target='_blank'>alt text guidelines</a> for tips.", 'max_length': 255, 'required': False}), 21: ('wagtail.blocks.CharBlock', (), {'help_text': "Use sentence case (e.g., 'Donate', 'Read more').", 'label': 'Link text', 'max_length': 50}), 22: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('page', 'Page'), ('file', 'File'), ('custom_url', 'Custom URL'), ('email', 'Email'), ('anchor', 'Anchor'), ('phone', 'Phone')], 'classname': 'link_choice_type_selector', 'label': 'Link to', 'required': False}), 23: ('wagtail.blocks.PageChooserBlock', (), {'form_classname': 'page_link', 'label': 'Page', 'required': False}), 24: ('wagtail.documents.blocks.DocumentChooserBlock', (), {'form_classname': 'file_link', 'label': 'File', 'required': False}), 25: ('wagtail.blocks.CharBlock', (), {'form_classname': 'custom_url_link url_field', 'label': 'Custom URL', 'max_length': 300, 'required': False, 'validators': [wagtail.admin.forms.choosers.URLOrAbsolutePathValidator()]}), 26: ('wagtail.blocks.CharBlock', (), {'form_classname': 'anchor_link', 'label': '#', 'max_length': 300, 'required': False}), 27: ('wagtail.blocks.EmailBlock', (), {'required': False}), 28: ('wagtail.blocks.CharBlock', (), {'form_classname': 'phone_link', 'label': 'Phone', 'max_length': 30, 'required': False}), 29: ('wagtail.blocks.BooleanBlock', (), {'form_classname': 'new_window_toggle', 'label': 'Open in new window', 'required': False}), 30: ('wagtail.blocks.StructBlock', [[('link_to', 22), ('page', 23), ('file', 24), ('custom_url', 25), ('anchor', 26), ('email', 27), ('phone', 28), ('new_window', 29)]], {'label': 'Link destination'}), 31: ('wagtail.blocks.CharBlock', (), {'help_text': "Optional: Add an ID to make this section linkable (e.g., 'donate', 'support').", 'max_length': 100, 'required': False}), 32: ('wagtail.blocks.StructBlock', [[('anchor_id', 31), ('background_color', 1)]], {}), 33: ('wagtail.blocks.StructBlock', [[('heading', 17), ('body', 18), ('image', 19), ('image_alt', 20), ('cta_text', 21), ('cta_link', 30), ('settings', 32)]], {}), 34: ('wagtail.blocks.CharBlock', (), {'help_text': "Optional: Add an ID to make this section linkable (e.g., 'news', 'gallery').", 'max_length': 100, 'required': False}), 35: ('wagtail.blocks.StructBlock', [[('anchor_id', 34), ('background_color', 1)]], {}), 36: ('wagtail.blocks.CharBlock', (), {'max_length': 255, 'required': False}), 37: ('wagtail.blocks.RichTextBlock', (), {'features': ['bold', 'link'], 'required': False}), 38: ('wagtail.blocks.TextBlock', (), {'help_text': "Short blurb about what you're linking to.", 'required': False}), 39: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('', 'None'), ('community', 'Community'), ('event', 'Event'), ('impact', 'Impact'), ('partnership', 'Partnership'), ('policy', 'Policy'), ('product', 'Product'), ('program', 'Program'), ('project', 'Project'), ('research', 'Research')], 'required': False}), 40: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Upload a 2:1 aspect ratio image at 1400×700px - this is displayed on mobile browsers. Wagtail will crop it for displaying at your chosen aspect ratios for desktop.'}), 41: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('2:1', '2:1 Wide landscape'), ('1:1', '1:1 Square'), ('5:4', '5:4 Landscape'), ('4:5', '4:5 Portrait'), ('2:3', '2:3 Tall portrait')], 'help_text': 'Aspect ratio for the image on desktop. The image will be cropped to fit.'}), 42: ('wagtail.blocks.CharBlock', (), {'help_text': "Use sentence case (e.g., 'Read more', 'Watch now').", 'label': 'Call to action text (optional)', 'max_length': 100, 'required': False}), 43: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('fifth', 'Fifth (20%)'), ('quarter', 'Quarter (25%)'), ('third', 'Third (33%)'), ('half', 'Half (50%)'), ('three-quarters', 'Three-quarters (75%)')], 'help_text': 'Width of the tile in the gallery grid at desktop sizes.'}), 44: ('wagtail.blocks.StructBlock', [[('heading', 17), ('body', 38), ('tag', 39), ('image', 40), ('image_ratio', 41), ('image_alt', 20), ('cta_link', 30), ('cta_text', 42), ('width', 43)]], {}), 45: ('wagtail.blocks.ListBlock', (44,), {'help_text': 'Add gallery tiles. For best results, ensure tile widths add up to 100% per row.', 'min_num': 1}), 46: ('wagtail.blocks.StructBlock', [[('settings', 35), ('heading', 36), ('intro', 37), ('tiles', 45)]], {}), 47: ('wagtail.blocks.CharBlock', (), {'help_text': 'Section heading. Use sentence case.', 'max_length': 255}), 48: ('wagtail.images.blocks.ImageChooserBlock', (), {'help_text': 'Ideal image size is 1376 * 515.'}), 49: ('wagtail.blocks.CharBlock', (), {'help_text': 'Sub heading. Use sentence case.', 'max_length': 255, 'required': False}), 50: ('wagtail.blocks.CharBlock', (), {'help_text': "Use sentence case (e.g., 'Read the report', 'Read more').", 'label': 'Link text', 'max_length': 50, 'required': False}), 51: ('wagtail.blocks.CharBlock', (), {'help_text': "Optional: Add an ID to make this section linkable (e.g., 'showcase', 'support').", 'max_length': 100, 'required': False}), 52: ('wagtail.blocks.BooleanBlock', (), {'default': False, 'help_text': 'Make the title and body content into a two-column layout.', 'inline_form': True, 'label': 'Make it two column layout', 'required': False}), 53: ('wagtail.blocks.StructBlock', [[('anchor_id', 51), ('background_color', 1), ('two_column_layout', 52)]], {}), 54: ('wagtail.blocks.StructBlock', [[('heading', 47), ('body', 18), ('image', 48), ('image_alt', 20), ('sub_heading', 49), ('cta_text', 50), ('cta_link', 30), ('settings', 53)]], {}), 55: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('light', 'White'), ('dark', 'Dark'), ('green', 'Green'), ('orange', 'Orange'), ('pink', 'Pink'), ('gray', 'Gray'), ('dark-alt', 'Dark-Alt')], 'help_text': 'This should match the background color of the previous section'}), 56: ('wagtail.blocks.ChoiceBlock', [], {'choices': [('light', 'White'), ('dark', 'Dark'), ('green', 'Green'), ('orange', 'Orange'), ('pink', 'Pink'), ('gray', 'Gray'), ('dark-alt', 'Dark-Alt')], 'help_text': 'This should match the background color of the next section'}), 57: ('wagtail.blocks.StructBlock', [[('top_color', 55), ('bottom_color', 56)]], {})}, help_text='Add content blocks for the homepage. Blocks will render in the order shown.', null=True),
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ <h3 class="m24-c-intro-title m24-t-sm" itemprop="sectionTitle">{{ value.heading
link_url=item.url|add_utm_parameters,
link_attributes=item.preview,
type=item.type,
type_icon=item.icon,
type_icon=item.type,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: are we confident that these two are interchangeable? icon was always all-lowercase but type looks like it's title case/has a leading capital. Is that handled at template render? The test, below, deliberately downcases to match a string in the HTML, so I am assuming it's handled already

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The icon function lowercases it 👍

topic=item.topic,
author=item.author,
preview=item.preview
Expand Down
1 change: 0 additions & 1 deletion bedrock/mozorg/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ class SpringboardItemBlockFactory(wagtail_factories.StructBlockFactory):
url = "https://example.com/article"
link_attributes = ""
type = "Article"
icon = "article"
topic = "News"
author = "Test Author"
preview = "Test preview text"
Expand Down
6 changes: 3 additions & 3 deletions bedrock/mozorg/tests/test_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,9 @@ def assert_springboard_block_content(section_element: BeautifulSoup, variant_dat
assert expected_item["type"] in type_div.get_text(), f"Wrong type text in item {index}"

# Check icon if present
if expected_item.get("icon"):
icon = item.find("span", class_=f"m24-c-springboard-icon-{expected_item['icon'].lower()}")
assert icon is not None, f"Icon with class 'm24-c-springboard-icon-{expected_item['icon'].lower()}' not found in item {index}"
if expected_item.get("type"):
icon = item.find("span", class_=f"m24-c-springboard-icon-{expected_item['type'].lower()}")
assert icon is not None, f"Icon with class 'm24-c-springboard-icon-{expected_item['type'].lower()}' not found in item {index}"

# Check author
author_div = item.find(class_="m24-c-springboard-author")
Expand Down
Loading