Skip to content

Commit

Permalink
Homepage refresh new intro section (#12858)
Browse files Browse the repository at this point in the history
* New section markup and layout (mobile + desktop)

* Add model updates, migration and layout tags

* Remove `cause_statement` fields from `Homepage` model, `page` from `FocusArea` model

* Remove remaining `cause_statement` references

* Fix import order in migration

* Update migration timestamp

* Fix invalid html classname in markup

* Fix focus area styling

* Remove remaining `page` references for `FocusArea` models

* Fix `FocusArea` responsive width

* Update migration to replace seed data and field lengths

* Remove character limit for updated fields since it crashes with existing data

* Fix migration to adapt to format and include locale_id for newly created FocusArea objects

* Test fix for CI factory workflow

* Assign a page to hero_bottom_page so button shows up in visual regression tests

* Streamline migration to use existing record instead of deleting and creating

* Migration formatting

* Update migration to keep cause_statement section and name the "Hero intro" section accordingly

* Update migration order

* Update model and migration to use `LinkBlock` field type to store `hero_intro_xxxx` data

* Fix default text line width

* Fix linting

* Separate migrations
  • Loading branch information
ramram-mf authored Sep 23, 2024
1 parent 3dca6d0 commit 961cf16
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 28 deletions.
12 changes: 12 additions & 0 deletions network-api/networkapi/utility/faker/streamfield_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 = []
Expand Down
5 changes: 5 additions & 0 deletions network-api/networkapi/wagtailpages/factory/homepage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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')
Expand Down
Original file line number Diff line number Diff line change
@@ -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",
),
]
Original file line number Diff line number Diff line change
@@ -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,
),
),
]
40 changes: 31 additions & 9 deletions network-api/networkapi/wagtailpages/pagemodels/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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 = [
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
{% load wagtailimages_tags i18n %}
{% load wagtailimages_tags %}

<div class="col-12 col-lg-4 mb-3 mb-lg-0 d-block d-sm-flex flex-sm-row flex-lg-column">
{% image area.interest_icon width-100 class="icon flex-shrink-0 mb-3 mb-sm-0 mb-lg-3 mr-sm-5 align-self-start" alt=area.interest_icon.title %}
<div class="tw-flex tw-flex-col tw-items-center medium:tw-flex-row tw-gap-16 medium:tw-mx-auto medium:tw-w-[29rem]">
{% image area.interest_icon width-100 class="tw-max-w-[4em] tw-max-h-[4em]" alt=area.interest_icon.title %}

<div class="focus-content">
<h2 class="tw-h4-heading">{{ area.name }}</h2>
<div class="tw-text-center medium:tw-text-left">
<h2 class="tw-font-zilla tw-text-[40px] tw-mb-0">{{ area.name }}</h2>
<p>{{ area.description }}</p>

{% if area.page %}<div class="mb-4 learn-more-link">
<a href="{{ area.page.localized.url }}" aria-label="{% blocktrans with name=area.name %}Learn more about: {{ name }}{% endblocktrans %}">{% trans "Learn more →" %}</a>
</div>{% endif %}
</div>
</div>

Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
{% load wagtailimages_tags i18n %}

<div class="row areas-of-focus">
<div class="col my-3 my-sm-5">
<h2 class="focus-heading text-center mb-4">{% trans "Our areas of focus" %}</h2>
<div class="row">
{% for focus in page.focus_areas.all %}
{% include "./focus_area.html" with area=focus.area %}
{% endfor %}
</div>
</div>
<div class="areas-of-focus tw-bg-blue-03 large:tw-bg-transparent tw-py-24 tw-flex tw-flex-col tw-gap-8 large:tw-flex-shrink-0 large:tw-py-40">
{% for focus in page.focus_areas.all %}
{% include "./focus_area.html" with area=focus.area %}
{% endfor %}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% load wagtailcore_tags %}

<div class="tw-container tw-flex tw-flex-col tw-my-24 medium:!tw-px-0 medium:tw-my-40">
<h2 class="tw-leading-tight tw-mb-8 medium:tw-text-[28px]">{{ page.hero_intro_heading }}</h2>
<p>{{ page.hero_intro_body }}</p>
{% if page.hero_intro_link %}
{% with link=page.hero_intro_link.0.value %}
<a href="{{ link.url }}" {% if link.new_window %}target="_blank"{% endif %} class="tw-cta-link d-inline-block tw-mt-2 tw-mb-5">{{ link.label }}</a>
{% endwith %}
{% endif %}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
{% if page.show_cause_statement %}
{% include "./fragments/cause_statement.html" %}
{% endif %}
</div>
<div class="tw-flex tw-flex-col large:tw-flex-row large:tw-gap-40 large:tw-container">
{% include "./fragments/hero_intro_box.html" %}
{% include "./fragments/focus_areas.html" %}
</div>

Expand Down
2 changes: 1 addition & 1 deletion network-api/networkapi/wagtailpages/wagtail_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ class AreasOfFocusViewSet(SnippetViewSet):
menu_order = 000
menu_label = "Areas of Focus"
menu_name = "Areas of Focus"
list_display = ("name", "interest_icon", "page")
list_display = ("name", "interest_icon")
search_fields = ("name",)
ordering = ("name",)

Expand Down

0 comments on commit 961cf16

Please sign in to comment.