Skip to content

Commit

Permalink
Allow newsletter signup module to have two optional name fields & upd…
Browse files Browse the repository at this point in the history
…ate newsletter module on Bannered Campaign Page (#11761)

* removed a styling class that's not needed

* improvement of the existing code

* repurposed the existing input-email.jsx to a general input-text.jsx

* Allow newsletter module to show two optional fields (first name and last name) & replaced the newsletter module on Bannered Campaign Page to use to new implementation approach.

* allow options to show country field and language field by default
  • Loading branch information
mmmavis authored Jan 25, 2024
1 parent 95fd73e commit 2d61300
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@
{% if page.signup %}
{% with localized_signup=page.signup.localized %}
<div
class="join-us mb-5"
class="newsletter-signup-module tw-mb-24"
data-module-type="default"
data-form-style="bannered-campaign-body"
data-show-country-field-by-default="true"
data-show-language-field-by-default="true"
data-button-text="{% trans "Sign up" context "Submit button for newsletter signup form" %}"
data-signup-id="{{ localized_signup.id }}"
data-cta-header="{{ localized_signup.header | escape }}"
data-cta-description="{{ localized_signup.description | escape }}"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
{{ cta.type }}

{% if cta_type == 'petition' %}
{% include './cta/petition.html' %}
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ const FIELD_CLASSES = `
tw-pr-18
`;

const InputEmail = ({
const InputText = ({
type,
ariaLabel,
outerMarginClasses = "",
errorMessage,
Expand All @@ -31,7 +32,7 @@ const InputEmail = ({
}) => {
let inputField = (
<input
type="email"
type={type}
className={classNames(FIELD_CLASSES, {
"tw-border-black": fieldStyle === "outlined",
})}
Expand Down Expand Up @@ -72,18 +73,19 @@ const InputEmail = ({
);
};

InputEmail.propTypes = {
InputText.propTypes = {
id: PropTypes.string.isRequired,
type: PropTypes.oneOf(["text", "email"]),
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
placeholder: PropTypes.string,
onFocus: PropTypes.func.isRequired,
onInput: PropTypes.func.isRequired,
onInput: PropTypes.func,
onChange: PropTypes.func.isRequired,
required: PropTypes.bool,
ariaLabel: PropTypes.string,
errorMessage: PropTypes.string,
fieldStyle: PropTypes.oneOf(["outlined", "filled"]),
};

export default InputEmail;
export default InputText;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import classNames from "classnames";
import Heading from "../atoms/heading.jsx";
import Description from "../atoms/description.jsx";
import InputEmail from "../atoms/input-email.jsx";
import InputText from "../atoms/input-text.jsx";
import Select from "../atoms/select.jsx";
import InputCheckboxWithLabel from "../molecules/input-checkbox-with-label.jsx";
import ButtonSubmit from "../atoms/button-submit.jsx";
Expand All @@ -23,6 +23,8 @@ class DefaultSignupForm extends Component {
super(props);
this.state = this.getInitialState();
this.ids = this.generateFieldIds([
"firstName",
"lastName",
"email",
"country",
"language",
Expand All @@ -35,12 +37,17 @@ class DefaultSignupForm extends Component {
getInitialState() {
return {
formData: {
firstName: "",
lastName: "",
email: "",
country: "",
language: getCurrentLanguage(),
privacy: "",
},
showAllFields: false,
showCountryField:
this.props.showCountryFieldByDefault?.toLowerCase() === "true",
showLanguageField:
this.props.showCountryFieldByDefault?.toLowerCase() === "true",
submitButtonDisabled: this.props.disableSubmitButtonByDefault,
};
}
Expand All @@ -58,16 +65,6 @@ class DefaultSignupForm extends Component {
}, {});
}

showAllFields() {
ReactGA.event({
category: `signup`,
action: `form focus`,
label: `Signup form input focused`,
});

this.setState({ showAllFields: true });
}

updateFormFieldValue(name, value) {
this.setState((prevState) => ({
formData: {
Expand All @@ -90,21 +87,46 @@ class DefaultSignupForm extends Component {
}
}

handleInputFocus() {
ReactGA.event({
category: `signup`,
action: `form focus`,
label: `Signup form input focused`,
});
}

handleFirstNameChange(event) {
this.updateFormFieldValue(event.target.name, event.target.value);
}

handleLastNameChange(event) {
this.updateFormFieldValue(event.target.name, event.target.value);
}

handleEmailFocusAndInput() {
this.handleInputFocus();

this.setState({ showCountryField: true, showLanguageField: true });
}

handleEmailChange(event) {
this.updateFormFieldValue("email", event.target.value);
this.updateFormFieldValue(event.target.name, event.target.value);
this.toggleSubmitButton(event.target.value === "");
}

handleCountryChange(event) {
this.updateFormFieldValue("country", event.target.value);
this.updateFormFieldValue(event.target.name, event.target.value);
}

handleLanguageChange(event) {
this.updateFormFieldValue("language", event.target.value);
this.updateFormFieldValue(event.target.name, event.target.value);
}

handlePrivacyChange(event) {
this.updateFormFieldValue("privacy", event.target.checked.toString());
this.updateFormFieldValue(
event.target.name,
event.target.checked.toString()
);
}

renderHeader() {
Expand All @@ -131,18 +153,59 @@ class DefaultSignupForm extends Component {
);
}

renderFirstNameField() {
const name = "firstName";

return (
<InputText
id={this.ids[name]}
name={name}
label={getText(`First name`)}
value={this.getFormFieldValue(name)}
placeholder={getText(`First name`)}
onFocus={() => this.handleInputFocus()}
onChange={(event) => this.handleFirstNameChange(event)}
required={false}
outerMarginClasses={FIELD_MARGIN_CLASSES}
errorMessage={this.props.errors[name]}
fieldStyle={this.style.fieldStyle}
/>
);
}

renderLastNameField() {
const name = "lastName";

return (
<InputText
id={this.ids[name]}
name={name}
label={getText(`Last name`)}
value={this.getFormFieldValue(name)}
placeholder={getText(`Last name`)}
onFocus={() => this.handleInputFocus()}
onChange={(event) => this.handleLastNameChange(event)}
required={false}
outerMarginClasses={FIELD_MARGIN_CLASSES}
errorMessage={this.props.errors[name]}
fieldStyle={this.style.fieldStyle}
/>
);
}

renderEmailField() {
const name = "email";

return (
<InputEmail
id={this.ids.email}
<InputText
id={this.ids[name]}
type="email"
name={name}
label={getText(`Email address`)}
value={this.getFormFieldValue(name)}
placeholder={getText(`Please enter your email`)}
onFocus={() => this.showAllFields()}
onInput={() => this.showAllFields()}
onFocus={() => this.handleEmailFocusAndInput()}
onInput={() => this.handleEmailFocusAndInput()}
onChange={(event) => this.handleEmailChange(event)}
required={true}
outerMarginClasses={FIELD_MARGIN_CLASSES}
Expand All @@ -152,33 +215,37 @@ class DefaultSignupForm extends Component {
);
}

renderAdditionalFields() {
const nameCountry = "country";
const nameLanguage = "language";
renderCountryField() {
const name = "country";

return (
<>
<Select
id={this.ids.country}
name={nameCountry}
value={this.getFormFieldValue(nameCountry)}
options={COUNTRY_OPTIONS}
onChange={(event) => this.handleCountryChange(event)}
required={false}
outerMarginClasses={FIELD_MARGIN_CLASSES}
fieldStyle={this.style.fieldStyle}
/>
<Select
id={this.ids.language}
name={nameLanguage}
value={this.getFormFieldValue(nameLanguage)}
options={LANGUAGE_OPTIONS}
onChange={(event) => this.handleLanguageChange(event)}
required={false}
outerMarginClasses={FIELD_MARGIN_CLASSES}
fieldStyle={this.style.fieldStyle}
/>
</>
<Select
id={this.ids[name]}
name={name}
value={this.getFormFieldValue(name)}
options={COUNTRY_OPTIONS}
onChange={(event) => this.handleCountryChange(event)}
required={false}
outerMarginClasses={FIELD_MARGIN_CLASSES}
fieldStyle={this.style.fieldStyle}
/>
);
}

renderLanguageField() {
const name = "language";

return (
<Select
id={this.ids[name]}
name={name}
value={this.getFormFieldValue(name)}
options={LANGUAGE_OPTIONS}
onChange={(event) => this.handleLanguageChange(event)}
required={false}
outerMarginClasses={FIELD_MARGIN_CLASSES}
fieldStyle={this.style.fieldStyle}
/>
);
}

Expand All @@ -187,7 +254,7 @@ class DefaultSignupForm extends Component {

return (
<InputCheckboxWithLabel
id={this.ids.privacy}
id={this.ids[name]}
name={name}
label={getText(
`I'm okay with Mozilla handling my info as explained in this Privacy Notice`
Expand All @@ -212,7 +279,7 @@ class DefaultSignupForm extends Component {
let buttonWrapperClasses = classNames({
"tw-flex-shrink-0 tw-mt-8 medium:tw-mt-0":
this.style.buttonPosition !== "bottom",
"tw-mt-24 medium:-tw-mb-16 medium:tw-mt-12 tw-text-right":
"tw-mt-24 medium:tw-mt-12 tw-text-right":
this.style.buttonPosition === "bottom",
});

Expand All @@ -224,8 +291,11 @@ class DefaultSignupForm extends Component {
<div className={containerClasses}>
<div className="tw-flex-grow">
<fieldset className={FIELD_MARGIN_CLASSES}>
{this.props.askName === "True" && this.renderFirstNameField()}
{this.props.askName === "True" && this.renderLastNameField()}
{this.renderEmailField()}
{this.state.showAllFields && this.renderAdditionalFields()}
{this.state.showCountryField && this.renderCountryField()}
{this.state.showLanguageField && this.renderLanguageField()}
</fieldset>
<fieldset>{this.renderPrivacyCheckbox()}</fieldset>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
*/

export const FORM_STYLE = {
"bannered-campaign-body": {
buttonPosition: "bottom",
buttonStyle: "primary",
buttonWidthClasses: "tw-w-full",
fieldStyle: "filled",
headingLevel: 3,
headingClass: "tw-h5-heading",
},
"blog-body": {
fieldStyle: "outlined",
headingLevel: 2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ function withSubmissionLogic(WrappedComponent) {
});

let payload = {
givenNames: formData.firstName,
surname: formData.lastName,
email: formData.email,
country: formData.country,
lang: formData.language,
Expand Down Expand Up @@ -269,7 +271,7 @@ function withSubmissionLogic(WrappedComponent) {
apiUrl: PropTypes.string.isRequired,
ctaHeader: PropTypes.string.isRequired,
ctaDescription: PropTypes.string.isRequired,
formPosition: PropTypes.string.isRequired,
formPosition: PropTypes.string,
whenLoaded: PropTypes.func,
};

Expand Down

0 comments on commit 2d61300

Please sign in to comment.