зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1649538 - Add new Snippets template for Send to Device r=k88hudson
Differential Revision: https://phabricator.services.mozilla.com/D83135
This commit is contained in:
Родитель
05bded91a1
Коммит
7e6bdb7722
|
@ -70,3 +70,7 @@ export const SendToDeviceSnippet = props => {
|
|||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const SendToDeviceScene2Snippet = props => {
|
||||
return <SendToDeviceSnippet expandedAlt={true} {...props} />;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
{
|
||||
"title": "SubmitFormSnippet",
|
||||
"description": "A template with two states: a SimpleSnippet and another that contains a form",
|
||||
"version": "1.2.0",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"plainText": {
|
||||
"description": "Plain text (no HTML allowed)",
|
||||
"type": "string"
|
||||
},
|
||||
"richText": {
|
||||
"description": "Text with HTML subset allowed: i, b, u, strong, em, br",
|
||||
"type": "string"
|
||||
},
|
||||
"link_url": {
|
||||
"description": "Target for links or buttons",
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "Two to five character string for the locale code"
|
||||
},
|
||||
"country": {
|
||||
"type": "string",
|
||||
"description": "Two character string for the country code (used for SMS)"
|
||||
},
|
||||
"section_title_icon": {
|
||||
"type": "string",
|
||||
"description": "Section title icon. 16x16px. SVG or PNG preferred. section_title_text must also be specified to display."
|
||||
},
|
||||
"section_title_icon_dark_theme": {
|
||||
"type": "string",
|
||||
"description": "Section title icon, dark theme variant. 16x16px. SVG or PNG preferred. section_title_text must also be specified to display."
|
||||
},
|
||||
"section_title_text": {
|
||||
"type": "string",
|
||||
"description": "Section title text. section_title_icon must also be specified to display."
|
||||
},
|
||||
"scene2_title": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/plainText"},
|
||||
{"description": "Title displayed before text in scene 2. Should be plain text."}
|
||||
]
|
||||
},
|
||||
"scene2_text": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/richText"},
|
||||
{"description": "Main body text of snippet. HTML subset allowed: i, b, u, strong, em, br"}
|
||||
]
|
||||
},
|
||||
"form_action": {
|
||||
"type": "string",
|
||||
"description": "Endpoint to submit form data."
|
||||
},
|
||||
"success_title": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Title shown before text on successful registration."
|
||||
},
|
||||
"success_text": {
|
||||
"type": "string",
|
||||
"description": "Message shown on successful registration."
|
||||
},
|
||||
"error_text": {
|
||||
"type": "string",
|
||||
"description": "Message shown if registration failed."
|
||||
},
|
||||
"scene2_email_placeholder_text": {
|
||||
"type": "string",
|
||||
"description": "Value to show while input is empty."
|
||||
},
|
||||
"scene2_input_placeholder": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Value to show while input is empty."
|
||||
},
|
||||
"scene2_button_label": {
|
||||
"type": "string",
|
||||
"description": "Label for form submit button"
|
||||
},
|
||||
"scene2_privacy_html": {
|
||||
"type": "string",
|
||||
"description": "Information about how the form data is used."
|
||||
},
|
||||
"scene2_disclaimer_html": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Html for disclaimer and link underneath input box."
|
||||
},
|
||||
"scene2_icon": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Image to display above the form. 98x98px. SVG or PNG preferred."
|
||||
},
|
||||
"scene2_icon_dark_theme": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Image to display above the form. Dark theme variant. 98x98px. SVG or PNG preferred."
|
||||
},
|
||||
"scene2_icon_alt_text": {
|
||||
"type": "string",
|
||||
"description": "Alt text describing scene2 icon for screen readers",
|
||||
"default": ""
|
||||
},
|
||||
"scene2_newsletter": {
|
||||
"type": "string",
|
||||
"description": "Newsletter/basket id user is subscribing to. Must be a value from the 'Slug' column here: https://basket.mozilla.org/news/. Default 'mozilla-foundation'."
|
||||
},
|
||||
"hidden_inputs": {
|
||||
"type": "object",
|
||||
"description": "Each entry represents a hidden input, key is used as value for the name property."
|
||||
},
|
||||
"retry_button_label": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/plainText"},
|
||||
{"description": "Text for the button in the event of a submission error/failure."}
|
||||
],
|
||||
"default": "Try again"
|
||||
},
|
||||
"do_not_autoblock": {
|
||||
"type": "boolean",
|
||||
"description": "Used to prevent blocking the snippet after the CTA (link or button) has been clicked"
|
||||
},
|
||||
"include_sms": {
|
||||
"type": "boolean",
|
||||
"description": "(send to device) Allow users to send an SMS message with the form?"
|
||||
},
|
||||
"message_id_sms": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Newsletter/basket id representing the SMS message to be sent."
|
||||
},
|
||||
"message_id_email": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Newsletter/basket id representing the email message to be sent. Must be a value from the 'Slug' column here: https://basket.mozilla.org/news/."
|
||||
},
|
||||
"utm_campaign": {
|
||||
"type": "string",
|
||||
"description": "(fxa) Value to pass through to GA as utm_campaign."
|
||||
},
|
||||
"utm_term": {
|
||||
"type": "string",
|
||||
"description": "(fxa) Value to pass through to GA as utm_term."
|
||||
},
|
||||
"links": {
|
||||
"additionalProperties": {
|
||||
"url": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/link_url"},
|
||||
{"description": "The url where the link points to."}
|
||||
]
|
||||
},
|
||||
"metric": {
|
||||
"type": "string",
|
||||
"description": "Custom event name sent with telemetry event."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["scene2_text"],
|
||||
"dependencies": {
|
||||
"section_title_icon": ["section_title_text"],
|
||||
"section_title_icon_dark_theme": ["section_title_text"]
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import { RichText } from "../../components/RichText/RichText";
|
|||
import { safeURI } from "../../template-utils";
|
||||
import { SimpleSnippet } from "../SimpleSnippet/SimpleSnippet";
|
||||
import { SnippetBase } from "../../components/SnippetBase/SnippetBase";
|
||||
import ConditionalWrapper from "../../components/ConditionalWrapper/ConditionalWrapper";
|
||||
|
||||
// Alt text placeholder in case the prop from the server isn't available
|
||||
const ICON_ALT_TEXT = "";
|
||||
|
@ -226,6 +227,53 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
renderForm() {
|
||||
return (
|
||||
<form
|
||||
action={this.props.form_action}
|
||||
method={this.props.form_method}
|
||||
onSubmit={this.handleSubmit}
|
||||
ref="form"
|
||||
>
|
||||
{this.renderHiddenFormInputs()}
|
||||
<div>
|
||||
{this.renderInput()}
|
||||
<button
|
||||
type="submit"
|
||||
className="ASRouterButton primary"
|
||||
onClick={this.handleSubmitAttempt}
|
||||
ref="formSubmitBtn"
|
||||
>
|
||||
{this.props.content.scene2_button_label}
|
||||
</button>
|
||||
</div>
|
||||
{this.renderFormPrivacyNotice() || this.renderDisclaimer()}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
renderScene2Icon() {
|
||||
const { content } = this.props;
|
||||
if (!content.scene2_icon) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="scene2Icon">
|
||||
<img
|
||||
src={safeURI(content.scene2_icon)}
|
||||
className="icon-light-theme"
|
||||
alt={content.scene2_icon_alt_text || ICON_ALT_TEXT}
|
||||
/>
|
||||
<img
|
||||
src={safeURI(content.scene2_icon_dark_theme || content.scene2_icon)}
|
||||
className="icon-dark-theme"
|
||||
alt={content.scene2_icon_alt_text || ICON_ALT_TEXT}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderSignupView() {
|
||||
const { content } = this.props;
|
||||
const containerClass = `SubmitFormSnippet ${this.props.className}`;
|
||||
|
@ -235,22 +283,7 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
className={containerClass}
|
||||
footerDismiss={true}
|
||||
>
|
||||
{content.scene2_icon ? (
|
||||
<div className="scene2Icon">
|
||||
<img
|
||||
src={safeURI(content.scene2_icon)}
|
||||
className="icon-light-theme"
|
||||
alt={content.scene2_icon_alt_text || ICON_ALT_TEXT}
|
||||
/>
|
||||
<img
|
||||
src={safeURI(
|
||||
content.scene2_icon_dark_theme || content.scene2_icon
|
||||
)}
|
||||
className="icon-dark-theme"
|
||||
alt={content.scene2_icon_alt_text || ICON_ALT_TEXT}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
{this.renderScene2Icon()}
|
||||
<div className="message">
|
||||
<p>
|
||||
{content.scene2_title && (
|
||||
|
@ -264,26 +297,70 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
)}
|
||||
</p>
|
||||
</div>
|
||||
<form
|
||||
action={this.props.form_action}
|
||||
method={this.props.form_method}
|
||||
onSubmit={this.handleSubmit}
|
||||
ref="form"
|
||||
>
|
||||
{this.renderHiddenFormInputs()}
|
||||
<div>
|
||||
{this.renderInput()}
|
||||
<button
|
||||
type="submit"
|
||||
className="ASRouterButton primary"
|
||||
onClick={this.handleSubmitAttempt}
|
||||
ref="formSubmitBtn"
|
||||
>
|
||||
{content.scene2_button_label}
|
||||
</button>
|
||||
</div>
|
||||
{this.renderFormPrivacyNotice() || this.renderDisclaimer()}
|
||||
</form>
|
||||
{this.renderForm()}
|
||||
</SnippetBase>
|
||||
);
|
||||
}
|
||||
|
||||
renderSectionHeader() {
|
||||
const { props } = this;
|
||||
|
||||
// an icon and text must be specified to render the section header
|
||||
if (props.content.section_title_icon && props.content.section_title_text) {
|
||||
const sectionTitleIconLight = safeURI(props.content.section_title_icon);
|
||||
const sectionTitleIconDark = safeURI(
|
||||
props.content.section_title_icon_dark_theme ||
|
||||
props.content.section_title_icon
|
||||
);
|
||||
const sectionTitleURL = props.content.section_title_url;
|
||||
|
||||
return (
|
||||
<div className="section-header">
|
||||
<h3 className="section-title">
|
||||
<ConditionalWrapper condition={sectionTitleURL}>
|
||||
<span
|
||||
className="icon icon-small-spacer icon-light-theme"
|
||||
style={{ backgroundImage: `url("${sectionTitleIconLight}")` }}
|
||||
/>
|
||||
<span
|
||||
className="icon icon-small-spacer icon-dark-theme"
|
||||
style={{ backgroundImage: `url("${sectionTitleIconDark}")` }}
|
||||
/>
|
||||
<span className="section-title-text">
|
||||
{props.content.section_title_text}
|
||||
</span>
|
||||
</ConditionalWrapper>
|
||||
</h3>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
renderSignupViewAlt() {
|
||||
const { content } = this.props;
|
||||
const containerClass = `SubmitFormSnippet ${this.props.className} scene2Alt`;
|
||||
return (
|
||||
<SnippetBase
|
||||
{...this.props}
|
||||
className={containerClass}
|
||||
// Don't show bottom dismiss button
|
||||
footerDismiss={false}
|
||||
>
|
||||
{this.renderSectionHeader()}
|
||||
{this.renderScene2Icon()}
|
||||
<div className="message">
|
||||
<p>
|
||||
{content.scene2_text && (
|
||||
<RichText
|
||||
scene2_text={content.scene2_text}
|
||||
localization_id="scene2_text"
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
{this.renderForm()}
|
||||
</div>
|
||||
</SnippetBase>
|
||||
);
|
||||
}
|
||||
|
@ -306,6 +383,10 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
if (this.state.expanded) {
|
||||
return this.renderSignupView();
|
||||
}
|
||||
// Render only scene 2 (signup view)
|
||||
if (this.props.expandedAlt) {
|
||||
return this.renderSignupViewAlt();
|
||||
}
|
||||
return (
|
||||
<SimpleSnippet
|
||||
{...this.props}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
width: 100%;
|
||||
|
||||
.disclaimerText {
|
||||
margin: 20px 0 0;
|
||||
margin: 5px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--newtab-text-secondary-color);
|
||||
}
|
||||
|
@ -72,7 +72,8 @@
|
|||
}
|
||||
|
||||
.innerWrapper {
|
||||
max-width: 670px;
|
||||
// https://github.com/mozmeao/snippets/blob/2054899350590adcb3c0b0a341c782b0e2f81d0b/activity-stream/newsletter-subscribe.html#L46
|
||||
max-width: 736px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
|
@ -121,6 +122,36 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.scene2Alt {
|
||||
text-align: start;
|
||||
|
||||
.scene2Icon {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.message {
|
||||
flex: 5;
|
||||
margin-bottom: 0;
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
width: 100%;
|
||||
|
||||
.icon {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.innerWrapper {
|
||||
padding: 0 0 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submissionStatus {
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
import { EOYSnippet } from "./EOYSnippet/EOYSnippet";
|
||||
import { FXASignupSnippet } from "./FXASignupSnippet/FXASignupSnippet";
|
||||
import { NewsletterSnippet } from "./NewsletterSnippet/NewsletterSnippet";
|
||||
import { SendToDeviceSnippet } from "./SendToDeviceSnippet/SendToDeviceSnippet";
|
||||
import {
|
||||
SendToDeviceSnippet,
|
||||
SendToDeviceScene2Snippet,
|
||||
} from "./SendToDeviceSnippet/SendToDeviceSnippet";
|
||||
import { SimpleBelowSearchSnippet } from "./SimpleBelowSearchSnippet/SimpleBelowSearchSnippet";
|
||||
import { SimpleSnippet } from "./SimpleSnippet/SimpleSnippet";
|
||||
|
||||
|
@ -15,6 +18,7 @@ export const SnippetsTemplates = {
|
|||
newsletter_snippet: NewsletterSnippet,
|
||||
fxa_signup_snippet: FXASignupSnippet,
|
||||
send_to_device_snippet: SendToDeviceSnippet,
|
||||
send_to_device_scene2_snippet: SendToDeviceScene2Snippet,
|
||||
eoy_snippet: EOYSnippet,
|
||||
simple_below_search_snippet: SimpleBelowSearchSnippet,
|
||||
};
|
||||
|
|
|
@ -3942,7 +3942,7 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
flex: 1 1 100%;
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet .disclaimerText {
|
||||
margin: 20px 0 0;
|
||||
margin: 5px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--newtab-text-secondary-color); }
|
||||
.SubmitFormSnippet p {
|
||||
|
@ -3984,7 +3984,7 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
display: flex;
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .innerWrapper {
|
||||
max-width: 670px;
|
||||
max-width: 736px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
|
@ -4015,6 +4015,22 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
.SubmitFormSnippet input.mainInput:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
.SubmitFormSnippet.scene2Alt {
|
||||
text-align: start; }
|
||||
.SubmitFormSnippet.scene2Alt .scene2Icon {
|
||||
flex: 1;
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .message {
|
||||
flex: 5;
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .message p {
|
||||
margin-bottom: 10px; }
|
||||
.SubmitFormSnippet.scene2Alt .section-header {
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet.scene2Alt .section-header .icon {
|
||||
margin-inline-end: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .innerWrapper {
|
||||
padding: 0 0 16px; }
|
||||
|
||||
.submissionStatus {
|
||||
text-align: center;
|
||||
|
|
|
@ -3945,7 +3945,7 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
flex: 1 1 100%;
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet .disclaimerText {
|
||||
margin: 20px 0 0;
|
||||
margin: 5px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--newtab-text-secondary-color); }
|
||||
.SubmitFormSnippet p {
|
||||
|
@ -3987,7 +3987,7 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
display: flex;
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .innerWrapper {
|
||||
max-width: 670px;
|
||||
max-width: 736px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
|
@ -4018,6 +4018,22 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
.SubmitFormSnippet input.mainInput:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
.SubmitFormSnippet.scene2Alt {
|
||||
text-align: start; }
|
||||
.SubmitFormSnippet.scene2Alt .scene2Icon {
|
||||
flex: 1;
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .message {
|
||||
flex: 5;
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .message p {
|
||||
margin-bottom: 10px; }
|
||||
.SubmitFormSnippet.scene2Alt .section-header {
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet.scene2Alt .section-header .icon {
|
||||
margin-inline-end: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .innerWrapper {
|
||||
padding: 0 0 16px; }
|
||||
|
||||
.submissionStatus {
|
||||
text-align: center;
|
||||
|
|
|
@ -3942,7 +3942,7 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
flex: 1 1 100%;
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet .disclaimerText {
|
||||
margin: 20px 0 0;
|
||||
margin: 5px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--newtab-text-secondary-color); }
|
||||
.SubmitFormSnippet p {
|
||||
|
@ -3984,7 +3984,7 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
display: flex;
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .innerWrapper {
|
||||
max-width: 670px;
|
||||
max-width: 736px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
|
@ -4015,6 +4015,22 @@ body[lwt-newtab-brighttext] .scene2Icon .icon-light-theme {
|
|||
.SubmitFormSnippet input.mainInput:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
.SubmitFormSnippet.scene2Alt {
|
||||
text-align: start; }
|
||||
.SubmitFormSnippet.scene2Alt .scene2Icon {
|
||||
flex: 1;
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .message {
|
||||
flex: 5;
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .message p {
|
||||
margin-bottom: 10px; }
|
||||
.SubmitFormSnippet.scene2Alt .section-header {
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet.scene2Alt .section-header .icon {
|
||||
margin-inline-end: 0; }
|
||||
.SubmitFormSnippet.scene2Alt .innerWrapper {
|
||||
padding: 0 0 16px; }
|
||||
|
||||
.submissionStatus {
|
||||
text-align: center;
|
||||
|
|
|
@ -12819,6 +12819,7 @@ function SubmitFormSnippet_extends() { SubmitFormSnippet_extends = Object.assign
|
|||
|
||||
|
||||
|
||||
|
||||
// Alt text placeholder in case the prop from the server isn't available
|
||||
|
||||
const SubmitFormSnippet_ICON_ALT_TEXT = "";
|
||||
|
@ -13052,32 +13053,8 @@ class SubmitFormSnippet_SubmitFormSnippet extends external_React_default.a.PureC
|
|||
});
|
||||
}
|
||||
|
||||
renderSignupView() {
|
||||
const {
|
||||
content
|
||||
} = this.props;
|
||||
const containerClass = `SubmitFormSnippet ${this.props.className}`;
|
||||
return external_React_default.a.createElement(SnippetBase_SnippetBase, SubmitFormSnippet_extends({}, this.props, {
|
||||
className: containerClass,
|
||||
footerDismiss: true
|
||||
}), content.scene2_icon ? external_React_default.a.createElement("div", {
|
||||
className: "scene2Icon"
|
||||
}, external_React_default.a.createElement("img", {
|
||||
src: Object(template_utils["safeURI"])(content.scene2_icon),
|
||||
className: "icon-light-theme",
|
||||
alt: content.scene2_icon_alt_text || SubmitFormSnippet_ICON_ALT_TEXT
|
||||
}), external_React_default.a.createElement("img", {
|
||||
src: Object(template_utils["safeURI"])(content.scene2_icon_dark_theme || content.scene2_icon),
|
||||
className: "icon-dark-theme",
|
||||
alt: content.scene2_icon_alt_text || SubmitFormSnippet_ICON_ALT_TEXT
|
||||
})) : null, external_React_default.a.createElement("div", {
|
||||
className: "message"
|
||||
}, external_React_default.a.createElement("p", null, content.scene2_title && external_React_default.a.createElement("h3", {
|
||||
className: "scene2Title"
|
||||
}, content.scene2_title), " ", content.scene2_text && external_React_default.a.createElement(RichText["RichText"], {
|
||||
scene2_text: content.scene2_text,
|
||||
localization_id: "scene2_text"
|
||||
}))), external_React_default.a.createElement("form", {
|
||||
renderForm() {
|
||||
return external_React_default.a.createElement("form", {
|
||||
action: this.props.form_action,
|
||||
method: this.props.form_method,
|
||||
onSubmit: this.handleSubmit,
|
||||
|
@ -13087,7 +13064,97 @@ class SubmitFormSnippet_SubmitFormSnippet extends external_React_default.a.PureC
|
|||
className: "ASRouterButton primary",
|
||||
onClick: this.handleSubmitAttempt,
|
||||
ref: "formSubmitBtn"
|
||||
}, content.scene2_button_label)), this.renderFormPrivacyNotice() || this.renderDisclaimer()));
|
||||
}, this.props.content.scene2_button_label)), this.renderFormPrivacyNotice() || this.renderDisclaimer());
|
||||
}
|
||||
|
||||
renderScene2Icon() {
|
||||
const {
|
||||
content
|
||||
} = this.props;
|
||||
|
||||
if (!content.scene2_icon) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return external_React_default.a.createElement("div", {
|
||||
className: "scene2Icon"
|
||||
}, external_React_default.a.createElement("img", {
|
||||
src: Object(template_utils["safeURI"])(content.scene2_icon),
|
||||
className: "icon-light-theme",
|
||||
alt: content.scene2_icon_alt_text || SubmitFormSnippet_ICON_ALT_TEXT
|
||||
}), external_React_default.a.createElement("img", {
|
||||
src: Object(template_utils["safeURI"])(content.scene2_icon_dark_theme || content.scene2_icon),
|
||||
className: "icon-dark-theme",
|
||||
alt: content.scene2_icon_alt_text || SubmitFormSnippet_ICON_ALT_TEXT
|
||||
}));
|
||||
}
|
||||
|
||||
renderSignupView() {
|
||||
const {
|
||||
content
|
||||
} = this.props;
|
||||
const containerClass = `SubmitFormSnippet ${this.props.className}`;
|
||||
return external_React_default.a.createElement(SnippetBase_SnippetBase, SubmitFormSnippet_extends({}, this.props, {
|
||||
className: containerClass,
|
||||
footerDismiss: true
|
||||
}), this.renderScene2Icon(), external_React_default.a.createElement("div", {
|
||||
className: "message"
|
||||
}, external_React_default.a.createElement("p", null, content.scene2_title && external_React_default.a.createElement("h3", {
|
||||
className: "scene2Title"
|
||||
}, content.scene2_title), " ", content.scene2_text && external_React_default.a.createElement(RichText["RichText"], {
|
||||
scene2_text: content.scene2_text,
|
||||
localization_id: "scene2_text"
|
||||
}))), this.renderForm());
|
||||
}
|
||||
|
||||
renderSectionHeader() {
|
||||
const {
|
||||
props
|
||||
} = this; // an icon and text must be specified to render the section header
|
||||
|
||||
if (props.content.section_title_icon && props.content.section_title_text) {
|
||||
const sectionTitleIconLight = Object(template_utils["safeURI"])(props.content.section_title_icon);
|
||||
const sectionTitleIconDark = Object(template_utils["safeURI"])(props.content.section_title_icon_dark_theme || props.content.section_title_icon);
|
||||
const sectionTitleURL = props.content.section_title_url;
|
||||
return external_React_default.a.createElement("div", {
|
||||
className: "section-header"
|
||||
}, external_React_default.a.createElement("h3", {
|
||||
className: "section-title"
|
||||
}, external_React_default.a.createElement(ConditionalWrapper_ConditionalWrapper, {
|
||||
condition: sectionTitleURL
|
||||
}, external_React_default.a.createElement("span", {
|
||||
className: "icon icon-small-spacer icon-light-theme",
|
||||
style: {
|
||||
backgroundImage: `url("${sectionTitleIconLight}")`
|
||||
}
|
||||
}), external_React_default.a.createElement("span", {
|
||||
className: "icon icon-small-spacer icon-dark-theme",
|
||||
style: {
|
||||
backgroundImage: `url("${sectionTitleIconDark}")`
|
||||
}
|
||||
}), external_React_default.a.createElement("span", {
|
||||
className: "section-title-text"
|
||||
}, props.content.section_title_text))));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
renderSignupViewAlt() {
|
||||
const {
|
||||
content
|
||||
} = this.props;
|
||||
const containerClass = `SubmitFormSnippet ${this.props.className} scene2Alt`;
|
||||
return external_React_default.a.createElement(SnippetBase_SnippetBase, SubmitFormSnippet_extends({}, this.props, {
|
||||
className: containerClass // Don't show bottom dismiss button
|
||||
,
|
||||
footerDismiss: false
|
||||
}), this.renderSectionHeader(), this.renderScene2Icon(), external_React_default.a.createElement("div", {
|
||||
className: "message"
|
||||
}, external_React_default.a.createElement("p", null, content.scene2_text && external_React_default.a.createElement(RichText["RichText"], {
|
||||
scene2_text: content.scene2_text,
|
||||
localization_id: "scene2_text"
|
||||
})), this.renderForm()));
|
||||
}
|
||||
|
||||
getFirstSceneContent() {
|
||||
|
@ -13108,6 +13175,11 @@ class SubmitFormSnippet_SubmitFormSnippet extends external_React_default.a.PureC
|
|||
|
||||
if (this.state.expanded) {
|
||||
return this.renderSignupView();
|
||||
} // Render only scene 2 (signup view)
|
||||
|
||||
|
||||
if (this.props.expandedAlt) {
|
||||
return this.renderSignupViewAlt();
|
||||
}
|
||||
|
||||
return external_React_default.a.createElement(SimpleSnippet_SimpleSnippet, SubmitFormSnippet_extends({}, this.props, {
|
||||
|
@ -13298,6 +13370,11 @@ const SendToDeviceSnippet = props => {
|
|||
processFormData: processFormData
|
||||
}));
|
||||
};
|
||||
const SendToDeviceScene2Snippet = props => {
|
||||
return external_React_default.a.createElement(SendToDeviceSnippet, SendToDeviceSnippet_extends({
|
||||
expandedAlt: true
|
||||
}, props));
|
||||
};
|
||||
// CONCATENATED MODULE: ./content-src/asrouter/templates/SimpleBelowSearchSnippet/SimpleBelowSearchSnippet.jsx
|
||||
function SimpleBelowSearchSnippet_extends() { SimpleBelowSearchSnippet_extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return SimpleBelowSearchSnippet_extends.apply(this, arguments); }
|
||||
|
||||
|
@ -13443,6 +13520,7 @@ const SnippetsTemplates = {
|
|||
newsletter_snippet: NewsletterSnippet,
|
||||
fxa_signup_snippet: FXASignupSnippet,
|
||||
send_to_device_snippet: SendToDeviceSnippet,
|
||||
send_to_device_scene2_snippet: SendToDeviceScene2Snippet,
|
||||
eoy_snippet: EOYSnippet,
|
||||
simple_below_search_snippet: SimpleBelowSearchSnippet_SimpleBelowSearchSnippet
|
||||
};
|
||||
|
|
|
@ -383,6 +383,39 @@ const MESSAGES = () => [
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "SNIPPETS_SCENE2_SEND_TO_DEVICE_TEST",
|
||||
template: "send_to_device_scene2_snippet",
|
||||
content: {
|
||||
include_sms: true,
|
||||
locale: "en-CA",
|
||||
country: "us",
|
||||
message_id_sms: "ff-mobilesn-download",
|
||||
message_id_email: "download-firefox-mobile",
|
||||
scene2_icon: TEST_ICON,
|
||||
section_title_icon:
|
||||
"https://snippets.cdn.mozilla.net/media/icons/094b0707-ab65-4b2e-99a1-a84122b6ab26.png",
|
||||
section_title_text: "Messages from Firefox",
|
||||
|
||||
scene2_button_label: "Send",
|
||||
scene2_disclaimer_html:
|
||||
"The intended recipient of the email must have consented. <privacyLink>Learn more</privacyLink>.",
|
||||
scene2_input_placeholder: "Your email address or phone number",
|
||||
scene2_text:
|
||||
"Send Firefox to your phone and take a powerful independent browser with you.",
|
||||
scene2_title: "Let's do this!",
|
||||
|
||||
error_text: "Oops, there was a problem.",
|
||||
success_title: "Your download link was sent.",
|
||||
success_text: "Check your device for the email message!",
|
||||
links: {
|
||||
privacyLink: {
|
||||
url:
|
||||
"https://www.mozilla.org/privacy/websites/?sample_rate=0.001&snippet_name=7894",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "SNIPPETS_SEND_TO_DEVICE_TEST_NO_DARK_THEME",
|
||||
template: "send_to_device_snippet",
|
||||
|
|
|
@ -3,12 +3,14 @@ import SimpleBelowSearchSnippetSchema from "../../../content-src/asrouter/templa
|
|||
import SimpleSnippetSchema from "../../../content-src/asrouter/templates/SimpleSnippet/SimpleSnippet.schema.json";
|
||||
import { SnippetsTestMessageProvider } from "../../../lib/SnippetsTestMessageProvider.jsm";
|
||||
import SubmitFormSnippetSchema from "../../../content-src/asrouter/templates/SubmitFormSnippet/SubmitFormSnippet.schema.json";
|
||||
import SubmitFormScene2SnippetSchema from "../../../content-src/asrouter/templates/SubmitFormSnippet/SubmitFormScene2Snippet.schema.json";
|
||||
|
||||
const schemas = {
|
||||
simple_snippet: SimpleSnippetSchema,
|
||||
newsletter_snippet: SubmitFormSnippetSchema,
|
||||
fxa_signup_snippet: SubmitFormSnippetSchema,
|
||||
send_to_device_snippet: SubmitFormSnippetSchema,
|
||||
send_to_device_scene2_snippet: SubmitFormScene2SnippetSchema,
|
||||
eoy_snippet: EOYSnippetSchema,
|
||||
simple_below_search_snippet: SimpleBelowSearchSnippetSchema,
|
||||
};
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
import { mount } from "enzyme";
|
||||
import React from "react";
|
||||
import schema from "content-src/asrouter/templates/SendToDeviceSnippet/SendToDeviceSnippet.schema.json";
|
||||
import { SendToDeviceSnippet } from "content-src/asrouter/templates/SendToDeviceSnippet/SendToDeviceSnippet";
|
||||
import {
|
||||
SendToDeviceSnippet,
|
||||
SendToDeviceScene2Snippet,
|
||||
} from "content-src/asrouter/templates/SendToDeviceSnippet/SendToDeviceSnippet";
|
||||
import { SnippetsTestMessageProvider } from "lib/SnippetsTestMessageProvider.jsm";
|
||||
|
||||
const DEFAULT_CONTENT = SnippetsTestMessageProvider.getMessages().find(
|
||||
msg => msg.template === "send_to_device_snippet"
|
||||
).content;
|
||||
const DEFAULT_SCENE2_CONTENT = SnippetsTestMessageProvider.getMessages().find(
|
||||
msg => msg.template === "send_to_device_scene2_snippet"
|
||||
).content;
|
||||
|
||||
async function testBodyContains(body, key, value) {
|
||||
const regex = new RegExp(
|
||||
|
@ -174,4 +180,52 @@ describe("SendToDeviceSnippet", () => {
|
|||
assert.ok(testBodyContains(body, "msg_name", "foo"), "has msg_name");
|
||||
});
|
||||
});
|
||||
|
||||
describe("SendToDeviceScene2Snippet", () => {
|
||||
function mountWithProps(content = {}) {
|
||||
const props = {
|
||||
id: "foo123",
|
||||
content: Object.assign({}, DEFAULT_SCENE2_CONTENT, content),
|
||||
onBlock() {},
|
||||
onDismiss: sandbox.stub(),
|
||||
sendUserActionTelemetry: sandbox.stub(),
|
||||
onAction: sandbox.stub(),
|
||||
};
|
||||
return mount(<SendToDeviceScene2Snippet {...props} />);
|
||||
}
|
||||
|
||||
it("should render scene 2", () => {
|
||||
const wrapper = mountWithProps();
|
||||
|
||||
assert.lengthOf(wrapper.find(".scene2Icon"), 1, "Found scene 2 icon");
|
||||
assert.lengthOf(
|
||||
wrapper.find(".scene2Title"),
|
||||
0,
|
||||
"Should not have a large header"
|
||||
);
|
||||
});
|
||||
it("should have block button", () => {
|
||||
const wrapper = mountWithProps();
|
||||
|
||||
assert.lengthOf(
|
||||
wrapper.find(".blockButton"),
|
||||
1,
|
||||
"Found the block button"
|
||||
);
|
||||
});
|
||||
it("should render title text", () => {
|
||||
const wrapper = mountWithProps();
|
||||
|
||||
assert.lengthOf(
|
||||
wrapper.find(".section-title-text"),
|
||||
1,
|
||||
"Found the section title"
|
||||
);
|
||||
assert.lengthOf(
|
||||
wrapper.find(".section-title .icon"),
|
||||
2, // light and dark theme
|
||||
"Found scene 2 title"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче