diff --git a/network-api/networkapi/utility/faker/streamfield_provider.py b/network-api/networkapi/utility/faker/streamfield_provider.py index 65b8c7ce108..bbc5f315853 100644 --- a/network-api/networkapi/utility/faker/streamfield_provider.py +++ b/network-api/networkapi/utility/faker/streamfield_provider.py @@ -742,6 +742,17 @@ def generate_bg_cta_link_field(): return generate_field("link", link_value) +def generate_homepage_hero_intro_link(): + link_value = { + "link_to": "external_url", + "external_url": fake.url(schemes=["https"]), + "label": " ".join(fake.words(nb=3)), + "new_window": True, + } + + return generate_field("link", link_value) + + class StreamfieldProvider(BaseProvider): """ A custom Faker Provider for relative image urls, for use with factory_boy @@ -804,6 +815,7 @@ def streamfield(self, fields=None): "mixed_content": generate_mixed_content_field, "app_install_download_button": generate_app_install_download_button_field, "buyersguide_call_to_action_link": generate_bg_cta_link_field, + "homepage_hero_intro_link": generate_homepage_hero_intro_link, } streamfield_data = [] diff --git a/network-api/networkapi/wagtailpages/factory/homepage.py b/network-api/networkapi/wagtailpages/factory/homepage.py index fbb9fc6e9ed..9055c31679a 100644 --- a/network-api/networkapi/wagtailpages/factory/homepage.py +++ b/network-api/networkapi/wagtailpages/factory/homepage.py @@ -26,6 +26,9 @@ class Meta: hero_image = SubFactory(ImageFactory) cause_statement = Faker("text", max_nb_chars=150) # cause_statement_link_text and cause_statement_link_page are created at a later state + hero_intro_heading = Faker("text", max_nb_chars=60) + hero_intro_body = Faker("text", max_nb_chars=250) + hero_intro_link = Faker("streamfield", fields=["homepage_hero_intro_link"]) quote_image = SubFactory(ImageFactory) quote_text = Faker("text", max_nb_chars=300) quote_source_name = Faker("text", max_nb_chars=30) @@ -102,6 +105,8 @@ def generate(seed): print('Generating "who we are" Page (PrimaryPage)') wwa_page = PrimaryPageFactory.create(parent=home_page, title="Who we are", show_in_menus=True) + home_page.save() + reseed(seed) print('Generating child pages for "who we are" page') diff --git a/network-api/networkapi/wagtailpages/migrations/0163_remove_focusarea_page.py b/network-api/networkapi/wagtailpages/migrations/0163_remove_focusarea_page.py new file mode 100644 index 00000000000..c7a2f142baf --- /dev/null +++ b/network-api/networkapi/wagtailpages/migrations/0163_remove_focusarea_page.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.15 on 2024-09-23 19:40 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("wagtailpages", "0162_alter_articlepage_body"), + ] + + operations = [ + migrations.RemoveField( + model_name="focusarea", + name="page", + ), + ] diff --git a/network-api/networkapi/wagtailpages/migrations/0164_homepage_hero_intro_body_homepage_hero_intro_heading_and_more.py b/network-api/networkapi/wagtailpages/migrations/0164_homepage_hero_intro_body_homepage_hero_intro_heading_and_more.py new file mode 100644 index 00000000000..d5a2512429a --- /dev/null +++ b/network-api/networkapi/wagtailpages/migrations/0164_homepage_hero_intro_body_homepage_hero_intro_heading_and_more.py @@ -0,0 +1,106 @@ +# Generated by Django 4.2.15 on 2024-09-23 19:42 + +import wagtail.blocks +import wagtail.documents.blocks +import wagtail.fields +from django.db import migrations, models + +import networkapi.wagtailpages.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ("wagtailpages", "0163_remove_focusarea_page"), + ] + + operations = [ + migrations.AddField( + model_name="homepage", + name="hero_intro_body", + field=models.TextField( + blank=True, + default="Mozilla empowers consumers to demand better online privacy, trustworthy AI, and safe online experiences from Big Tech and governments. We work across borders, disciplines, and technologies to uphold principles like privacy, inclusion and decentralization online.", + max_length=300, + ), + ), + migrations.AddField( + model_name="homepage", + name="hero_intro_heading", + field=models.CharField( + blank=True, + default="A healthy internet is one in which privacy, openness, and inclusion are the norms.", + max_length=100, + ), + ), + migrations.AddField( + model_name="homepage", + name="hero_intro_link", + field=wagtail.fields.StreamField( + [ + ( + "link", + wagtail.blocks.StructBlock( + [ + ("label", wagtail.blocks.CharBlock()), + ( + "link_to", + wagtail.blocks.ChoiceBlock( + choices=[ + ("page", "Page"), + ("external_url", "External URL"), + ("relative_url", "Relative URL"), + ("email", "Email"), + ("anchor", "Anchor"), + ("file", "File"), + ("phone", "Phone"), + ], + label="Link to", + ), + ), + ("page", wagtail.blocks.PageChooserBlock(label="Page", required=False)), + ( + "external_url", + wagtail.blocks.URLBlock( + help_text="Enter a full URL including http:// or https://", + label="External URL", + max_length=300, + required=False, + ), + ), + ( + "relative_url", + wagtail.blocks.CharBlock( + help_text='A path relative to this domain. For example, "/foo/bar" or "?foo=bar".', + label="Relative URL", + max_length=300, + required=False, + validators=[networkapi.wagtailpages.validators.RelativeURLValidator()], + ), + ), + ( + "anchor", + wagtail.blocks.CharBlock( + help_text='An id attribute of an element on the current page. For example, "#section-1"', + label="#", + max_length=300, + required=False, + validators=[networkapi.wagtailpages.validators.AnchorLinkValidator()], + ), + ), + ("email", wagtail.blocks.EmailBlock(required=False)), + ("file", wagtail.documents.blocks.DocumentChooserBlock(label="File", required=False)), + ("phone", wagtail.blocks.CharBlock(label="Phone", max_length=30, required=False)), + ( + "new_window", + wagtail.blocks.BooleanBlock(label="Open in new window", required=False), + ), + ] + ), + ) + ], + blank=True, + use_json_field=True, + ), + ), + ] diff --git a/network-api/networkapi/wagtailpages/pagemodels/base.py b/network-api/networkapi/wagtailpages/pagemodels/base.py index e191bdb4d04..06473963b45 100644 --- a/network-api/networkapi/wagtailpages/pagemodels/base.py +++ b/network-api/networkapi/wagtailpages/pagemodels/base.py @@ -9,6 +9,8 @@ from wagtail.search import index from wagtail_localize.fields import SynchronizedField, TranslatableField +from networkapi.wagtailpages.pagemodels.customblocks.link_block import LinkBlock + # TODO: https://github.com/mozilla/foundation.mozilla.org/issues/2362 from ..donation_modal import DonationModals # noqa: F401 from ..utils import CharCountWidget, get_page_tree_information @@ -18,6 +20,14 @@ from .mixin.foundation_metadata import FoundationMetadataPageMixin from .mixin.foundation_navigation import FoundationNavigationPageMixin +hero_intro_heading_default_text = "A healthy internet is one in which privacy, openness, and inclusion are the norms." +hero_intro_body_default_text = ( + "Mozilla empowers consumers to demand better online privacy, trustworthy AI, " + "and safe online experiences from Big Tech and governments. We work across " + "borders, disciplines, and technologies to uphold principles like privacy, " + "inclusion and decentralization online." +) + class BasePage(FoundationMetadataPageMixin, FoundationNavigationPageMixin, Page): class Meta: @@ -604,19 +614,10 @@ class FocusArea(TranslatableMixin, models.Model): help_text="Description of this area of focus. Max. 300 characters.", ) - page = models.ForeignKey( - "wagtailcore.Page", - blank=True, - null=True, - on_delete=models.SET_NULL, - related_name="+", - ) - panels = [ FieldPanel("interest_icon"), FieldPanel("name"), FieldPanel("description"), - FieldPanel("page"), ] translatable_fields = [ @@ -764,6 +765,15 @@ def get_banner(self): hero_button_url = models.URLField(blank=True) + hero_intro_heading = models.CharField(max_length=100, blank=True, default=hero_intro_heading_default_text) + hero_intro_body = models.TextField(max_length=300, blank=True, default=hero_intro_body_default_text) + hero_intro_link = StreamField( + [("link", LinkBlock())], + use_json_field=True, + blank=True, + max_num=1, + ) + ideas_image = models.ForeignKey( "wagtailimages.Image", null=True, @@ -865,6 +875,15 @@ def get_banner(self): heading="cause statement", classname="collapsible collapsed", ), + MultiFieldPanel( + [ + FieldPanel("hero_intro_heading"), + FieldPanel("hero_intro_body"), + FieldPanel("hero_intro_link"), + ], + heading="Hero Intro Box", + classname="collapsible", + ), MultiFieldPanel( [ InlinePanel("focus_areas", min_num=3, max_num=3), @@ -933,6 +952,9 @@ def get_banner(self): SynchronizedField("hero_image"), TranslatableField("hero_button_text"), SynchronizedField("hero_button_url"), + TranslatableField("hero_intro_heading"), + TranslatableField("hero_intro_body"), + SynchronizedField("hero_intro_link"), SynchronizedField("ideas_image"), TranslatableField("ideas_headline"), TranslatableField("cause_statement"), diff --git a/network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/focus_area.html b/network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/focus_area.html index 0e57ebd3003..22c233d10ae 100644 --- a/network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/focus_area.html +++ b/network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/focus_area.html @@ -1,15 +1,11 @@ -{% load wagtailimages_tags i18n %} +{% load wagtailimages_tags %} -
{{ area.description }}
- - {% if area.page %}{% endif %}{{ page.hero_intro_body }}
+ {% if page.hero_intro_link %} + {% with link=page.hero_intro_link.0.value %} + {{ link.label }} + {% endwith %} + {% endif %} +