Skip to content

Commit

Permalink
Add Custom Privacy Text Option to CTAs (#12293)
Browse files Browse the repository at this point in the history
* Update CTA model to add richtext privacy_text

* Update templates to take advantage of new privacy_text when referencing a cta, or provide empty string if default

* Create new privacy notice js module

* Update newsletter signup component to render custom privacy text or default privacy text if no custom privacy text found

* CSS tweak to sync formassembly styling of richtext custom privacy text on petition pages

* Change to quotes

* Though not necessary to abstract to form-specific-style.js, we can reduce duplicate code a bit

* linting

* additional formatting

* Fix richtext filter

* Move tailwind classes to formassembly override scss

* Move conditional block and remove duplicate line

* Add data-cta-privacy-notice attribute or empty where possible, single quote for rich text filter

* Switch to | escape

* Remove stray quote, update migration to account for merge with main

* Move label logic to privacy-notice.jsx

* Update documentation for formassembly
  • Loading branch information
robdivincenzo authored May 31, 2024
1 parent 2629ad3 commit fcb5f03
Show file tree
Hide file tree
Showing 19 changed files with 117 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

{% load i18n l10n static wagtailimages_tags %}
{% load i18n l10n static wagtailcore_tags wagtailimages_tags %}

{% block block_content %}
<div class="tw-mx-8 large:tw-mx-0 tw-my-16 large:tw-my-20">
Expand All @@ -16,6 +16,7 @@
data-signup-id="{{ snippet_localized.id }}"
data-cta-header="{{ snippet_localized.header | escape }}"
data-cta-description="{{ snippet_localized.description | escape }}"
data-cta-privacy-notice="{{ snippet_localized.privacy_notice | escape }}"
data-ask-name="{{ snippet_localized.ask_name }}"
data-button-cta-event="newsletter-signup">
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% extends "fragments/footer.html" %}

{% load i18n l10n static %}
{% load wagtailcore_tags i18n l10n static %}

{% block footer_donate %}
<!-- nothing right now -->
Expand All @@ -17,7 +17,9 @@
data-signup-id="{{ localized_footer_signup.id }}"
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-cta-header="{{ localized_footer_signup.header | escape }}"
data-cta-description="{{ localized_footer_signup.description | escape }}">
data-cta-description="{{ localized_footer_signup.description | escape }}"
data-cta-privacy-notice="{{ localized_footer_signup.privacy_notice | escape }}"
>
</div>
{% endwith %}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-cta-header="{{ cta_header|default:_("Help shape the future of the web for the public good.") }}"
data-cta-description="<p class='tw-mb-12'>{{ cta_description|default:_("Join our Mozilla News email list to get action alerts & internet tips right to your inbox.") }}</p>"
data-cta-privacy-notice=""
></div>
</div>
1 change: 1 addition & 0 deletions network-api/networkapi/templates/fragments/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-cta-header="{% trans "Help shape the future of the web for the public good." %}"
data-cta-description="<p>{% trans "Join our <b>Mozilla News</b> email list to get action alerts & internet tips right to your inbox." %}</p>"
data-cta-privacy-notice=""
>
</div>
<a class="logo tw-block tw-my-24 medium:tw-my-0" href="https://foundation.mozilla.org" aria-label="{% trans 'Return to Homepage' %}"><img src="{% static "_images/mozilla-block-white.svg" %}" alt="{% trans 'Mozilla Foundation' %}" width="96"></a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-cta-header="{% trans "Help shape the future of the web for the public good." %}"
data-cta-description="<p>{% trans "Join our <b>Mozilla News</b> email list to get action alerts & internet tips right to your inbox." %}</p>"
data-cta-privacy-notice=""
></div>
<div class="text-center mt-3 d-lg-none">
<button class="tw-btn form-dismiss">{% trans "No thanks" %}</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 4.2.11 on 2024-05-28 18:33

import wagtail.fields
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("wagtailpages", "0136_alter_donationmodal_body_richtext"),
]

operations = [
migrations.AddField(
model_name="blogsignup",
name="privacy_notice",
field=wagtail.fields.RichTextField(
blank=True,
help_text="This optional privacy notice field will overwrite the default privacy notice text. If this field is left blank, the default privacy notice text is used.",
),
),
migrations.AddField(
model_name="cta",
name="privacy_notice",
field=wagtail.fields.RichTextField(
blank=True,
help_text="This optional privacy notice field will overwrite the default privacy notice text. If this field is left blank, the default privacy notice text is used.",
),
),
]
9 changes: 9 additions & 0 deletions network-api/networkapi/wagtailpages/pagemodels/campaigns.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from ..utils import get_content_related_by_tag, get_page_tree_information
from .base import PrimaryPage
from .customblocks.base_rich_text_options import base_rich_text_options
from .mixin.foundation_metadata import FoundationMetadataPageMixin
from .modular import MiniSiteNameSpace

Expand All @@ -31,6 +32,13 @@ class CTABase(models.Model):

description = RichTextField(help_text="Body (richtext) of component", blank=True)

privacy_notice = RichTextField(
help_text="This optional privacy notice field will overwrite the default privacy notice text. "
"If this field is left blank, the default privacy notice text is used.",
features=base_rich_text_options,
blank=True,
)

newsletter = models.CharField(
max_length=100,
help_text="The (pre-existing) newsletter to sign up for",
Expand All @@ -41,6 +49,7 @@ class CTABase(models.Model):
TranslatableField("name"),
TranslatableField("header"),
TranslatableField("description"),
TranslatableField("privacy_notice"),
SynchronizedField("newsletter"),
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@
data-signup-id="{{ localized_signup.id }}"
data-cta-header="{{ localized_signup.header | escape }}"
data-cta-description="{{ localized_signup.description | escape }}"
data-ask-name="{{ localized_signup.ask_name }}">
data-ask-name="{{ localized_signup.ask_name }}"
data-cta-privacy-notice="{{ localized_signup.privacy_notice|escape }}">
</div>
{% endwith %}
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-cta-header="{{ self.signup.header | escape }}"
data-cta-description="{{ self.signup.description | escape }}"
data-cta-privacy-notice="{{ self.signup.privacy_notice | escape }}"
></div>
{% endblock block_content %}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
data-signup-id="{{ self.signup.id | unlocalize }}"
data-cta-header="{{ self.signup.header | escape }}"
data-cta-description="{{ self.signup.description | escape }}"
data-cta-privacy-notice="{{ self.signup.privacy_notice | escape }}"
data-ask-name="{{ self.signup.ask_name }}"
data-button-cta-event="newsletter-signup"
></div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% load i18n %}
{% load i18n wagtailcore_tags %}

{% comment %}
*** IMPORTANT ***
Expand All @@ -13,7 +13,7 @@
- Go to petition.html and look for this line {% include "../../fragments/formassembly_body.html"
- Update the variable names to they match the new FormAssembly field names
- Plug in those variables into corresponding form fields in formassembly_body.html

4. If form field names are changed:
(Field ref: https://mozillafoundation.tfaforms.net/forms/builder/5.0.0/9 and click on "OUTLINE" tab)
- Update the bottom section of formassembly_override.scss to reflect new field names
Expand All @@ -39,6 +39,9 @@

9. Update the revision note on the next line. Revision number can be found on https://mozillafoundation.tfaforms.net/versions/index/9

10. Update the privacy_notice value to include an {%if %} tag and default value
- {% if privacy_notice %}{% blocktrans with privacy_notice=privacy_notice|richtext %}{{ privacy_notice }}{% endblocktrans %}{% else %}{% blocktrans with link="https://www.mozilla.org/privacy/websites/" %}I’m okay with Mozilla handling my info as explained in this <a href="{{ link }}" target="_blank">Privacy Notice</a>.{% endblocktrans %}{% endif %}

The code snippet below is based on FormAssembly form revision #32

*** NOTE ***
Expand Down Expand Up @@ -318,7 +321,7 @@
</div>
{% endif %}
<div class="oneField field-container-D labelsAbove " id="tfa_492-D" role="group" aria-labelledby="tfa_492-L" data-tfa-labelledby="-L tfa_492-L" aria-required="true">
<label id="tfa_492-L" class="label preField" aria-label="Privacy Agreement required">Privacy Agreement</label><br><div class="inputWrapper"><span id="tfa_492" class="choices vertical required" aria-required="true"><span class="oneChoice"><input type="checkbox" value="tfa_493" class="calc-DefaultName" id="tfa_493" name="tfa_493" aria-labelledby="tfa_493-L" data-tfa-labelledby="tfa_492-L tfa_493-L"><label class="label reqMark postField" id="tfa_493-L" for="tfa_493"><span class="input-checkbox-faux"></span>{% blocktrans with link="https://www.mozilla.org/privacy/websites/" %}I’m okay with Mozilla handling my info as explained in this <a href="{{ link }}" target="_blank">Privacy Notice</a>.{% endblocktrans %}</label></span></span></div>
<label id="tfa_492-L" class="label preField" aria-label="Privacy Agreement required">Privacy Agreement</label><br><div class="inputWrapper"><span id="tfa_492" class="choices vertical required" aria-required="true"><span class="oneChoice"><input type="checkbox" value="tfa_493" class="calc-DefaultName" id="tfa_493" name="tfa_493" aria-labelledby="tfa_493-L" data-tfa-labelledby="tfa_492-L tfa_493-L"><label class="label reqMark postField" id="tfa_493-L" for="tfa_493"><span class="input-checkbox-faux"></span>{% if privacy_notice %}{% blocktrans with privacy_notice=privacy_notice|richtext %}{{ privacy_notice }}{% endblocktrans %}{% else %}{% blocktrans with link="https://www.mozilla.org/privacy/websites/" %}I’m okay with Mozilla handling my info as explained in this <a href="{{ link }}" target="_blank">Privacy Notice</a>.{% endblocktrans %}{% endif %}</label></span></span></div>
</div>
<div class="oneField field-container-D " id="tfa_494-D" role="group" aria-labelledby="tfa_494-L" data-tfa-labelledby="-L tfa_494-L">
<label id="tfa_494-L" class="label preField ">Email Subscription</label><br><div class="inputWrapper"><span id="tfa_494" class="choices vertical "><span class="oneChoice"><input type="checkbox" value="tfa_495" class="" id="tfa_495" name="tfa_495" aria-labelledby="tfa_495-L" data-tfa-labelledby="tfa_494-L tfa_495-L"><label class="label postField" id="tfa_495-L" for="tfa_495"><span class="input-checkbox-faux"></span>{% trans "Yes, I want to receive email updates about Mozilla’s campaigns." %}</label></span></span></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
data-button-text="{% trans "Subscribe" context "Submit button for newsletter signup form" %}"
data-cta-header="{% trans "Subscribe to our newsletter" %}"
data-cta-description="<p class='tw-mb-12'>{% trans "Help shape the future of the web for the public good. Join our Mozilla News email list to get action alerts & internet tips right to your inbox." %}</p>"
data-cta-privacy-notice=""
></div>
{% if show_socials %}
<div class="tw-hidden medium:tw-block">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ <h2 class="take-action-title tw-mb-12">{{ page.take_action_title }}</h2>
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-cta-header="{% trans "Help shape the future of the web for the public good." %}"
data-cta-description="<p>{% trans "Join our <b>Mozilla News</b> email list to get action alerts & internet tips right to your inbox." %}</p>"
data-cta-privacy-notice=""
>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ <h2 class="tw-h2-heading">{% trans "With the RegretsReporter extension, you can
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-cta-header="{% trans "To stay updated on this campaign and our other work, sign up for Mozilla’s newsletter." %}"
data-cta-description=""
data-cta-privacy-notice=""
>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ <h5 class="tw-h5-heading">{{ cta.header | escape }}</h5>
We are inncluding tfa_* in the variable name to make it clear where the value should be plugged in.
For field name reference, see https://mozillafoundation.tfaforms.net/forms/definition/9
{% endcomment %}
{% include "../../fragments/formassembly_body.html" with csp_nonce=csp_nonce show_country_field=cta.show_country_field show_postal_code_field=cta.show_postal_code_field show_comment_field=cta.show_comment_field campaign_id_tfa_1=cta.campaign_id source_url_tfa_498=source_url lang_tfa_499=LANGUAGE_CODE thank_you_url_tfa_500=thank_you_url %}
{% include "../../fragments/formassembly_body.html" with csp_nonce=csp_nonce show_country_field=cta.show_country_field show_postal_code_field=cta.show_postal_code_field show_comment_field=cta.show_comment_field campaign_id_tfa_1=cta.campaign_id source_url_tfa_498=source_url lang_tfa_499=LANGUAGE_CODE thank_you_url_tfa_500=thank_you_url privacy_notice=cta.privacy_notice %}
<link rel="stylesheet" href="{% static "_css/formassembly-override.compiled.css" %}">
{% else %}
<div
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% load i18n %}
{% load wagtailcore_tags i18n %}

<div
class="newsletter-signup-module mb-5"
Expand All @@ -10,5 +10,6 @@
{% if cta.header %}
data-cta-header="{{ cta.header | escape }}"
{% endif %}
data-cta-description="{{ cta.description | escape }}">
data-cta-description="{{ cta.description | escape }}"
data-cta-privacy-notice="{{ cta.privacy_notice | escape }}">
</div>
32 changes: 32 additions & 0 deletions source/js/components/newsletter-signup/atoms/privacy-notice.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import { getText } from "../../petition/locales";
import PropTypes from "prop-types";

const PrivacyNotice = ({ content, classes }) => {
//[TODO] Investigate removing the legacy richtext template which renders an empty rich-text div wrapper
// Jira TP1-601 / Github Issue #12285 https://github.com/MozillaFoundation/foundation.mozilla.org/issues/12285
if (!content || content == "<div class='rich-text'></div>") {
content = getText(
`I'm okay with Mozilla handling my info as explained in this Privacy Notice`
);
}
if (typeof content === "string") {
return (
<span
dangerouslySetInnerHTML={{
__html: content,
}}
className={classes}
/>
);
}

return <span className={classes}>{content}</span>;
};

PrivacyNotice.propTypes = {
content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
classes: PropTypes.string,
};

export default PrivacyNotice;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PropTypes from "prop-types";
import classNames from "classnames";
import Heading from "../atoms/heading.jsx";
import Description from "../atoms/description.jsx";
import PrivacyNotice from "../atoms/privacy-notice.jsx";
import InputText from "../atoms/input-text.jsx";
import Select from "../atoms/select.jsx";
import InputCheckboxWithLabel from "../molecules/input-checkbox-with-label.jsx";
Expand Down Expand Up @@ -156,6 +157,15 @@ class DefaultSignupForm extends Component {
);
}

renderPrivacyNotice() {
return (
<PrivacyNotice
content={this.props.ctaPrivacyNotice}
classes="[&_p]:tw-body-small"
/>
);
}

renderAPIErrorMessage() {
if (!this.props.apiError) return null;

Expand Down Expand Up @@ -265,9 +275,7 @@ class DefaultSignupForm extends Component {
<InputCheckboxWithLabel
id={this.ids[name]}
name={name}
label={getText(
`I'm okay with Mozilla handling my info as explained in this Privacy Notice`
)}
label={this.renderPrivacyNotice()}
value={this.getFormFieldValue(name)}
checked={this.getFormFieldValue(name) === "true"}
onChange={(event) => this.handlePrivacyChange(event)}
Expand Down
9 changes: 9 additions & 0 deletions source/sass/formassembly-override.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ $input-font-size: 1.25rem !important;
label {
font-family: $font-family-sans-serif;
margin-bottom: 0;
.rich-text {
display: inline-block;
p {
display: inline-block;
//match styling for richtext fields like privacy_notice
color: #444;
font-size: 16px;
}
}
}
}

Expand Down

0 comments on commit fcb5f03

Please sign in to comment.