Skip to content
This repository has been archived by the owner on Feb 29, 2020. It is now read-only.

Commit

Permalink
Fix Bug 1492089 - Add EOY Template (#4487)
Browse files Browse the repository at this point in the history
  • Loading branch information
piatra committed Oct 18, 2018
1 parent 663a09e commit 45d8399
Show file tree
Hide file tree
Showing 18 changed files with 528 additions and 18 deletions.
2 changes: 2 additions & 0 deletions content-src/asrouter/asrouter-content.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {actionCreators as ac} from "common/Actions.jsm";
import {OUTGOING_MESSAGE_NAME as AS_GENERAL_OUTGOING_MESSAGE_NAME} from "content-src/lib/init-store";
import {EOYSnippet} from "./templates/EOYSnippet/EOYSnippet";
import {generateMessages} from "./rich-text-strings";
import {ImpressionsWrapper} from "./components/ImpressionsWrapper/ImpressionsWrapper";
import {LocalizationProvider} from "fluent-react";
Expand All @@ -16,6 +17,7 @@ const SnippetComponents = {
newsletter_snippet: props => <SubmitFormSnippet {...props} form_method="POST" />,
fxa_signup_snippet: props => <SubmitFormSnippet {...props} form_method="GET" />,
send_to_device_snippet: SendToDeviceSnippet,
eoy_snippet: props => <EOYSnippet {...props} form_method="GET" />,
};

const INCOMING_MESSAGE_NAME = "ASRouter:parent-to-child";
Expand Down
4 changes: 0 additions & 4 deletions content-src/asrouter/components/Button/_Button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
color: inherit;
cursor: pointer;

.tall & {
margin-inline-start: 20px;
}

&.primary {
border: 1px solid var(--newtab-button-primary-color);
background-color: var(--newtab-button-primary-color);
Expand Down
2 changes: 1 addition & 1 deletion content-src/asrouter/components/RichText/RichText.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function RichText(props) {
throw new Error(`ASRouter: ${props.localization_id} is not a valid rich text property. If you want it to be processed, you need to add it to asrouter/rich-text-strings.js`);
}
return (
<Localized id={props.localization_id} {...ALLOWED_TAGS} {...convertLinks(props.links, props.sendClick, props.autoBlock)}>
<Localized id={props.localization_id} {...ALLOWED_TAGS} {...props.customElements} {...convertLinks(props.links, props.sendClick, props.autoBlock)}>
<span>{props.text}</span>
</Localized>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class SnippetBase extends React.PureComponent {

const containerClassName = `SnippetBaseContainer${props.className ? ` ${props.className}` : ""}`;

return (<div className={containerClassName}>
return (<div className={containerClassName} style={this.props.textStyle}>
<div className="innerWrapper">
{props.children}
</div>
Expand Down
82 changes: 82 additions & 0 deletions content-src/asrouter/templates/EOYSnippet/EOYSnippet.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from "react";
import {SimpleSnippet} from "../SimpleSnippet/SimpleSnippet";

export class EOYSnippet extends React.PureComponent {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}

/**
* setFrequencyValue - `frequency` form parameter value should be `monthly`
* if `monthly-checkbox` is selected or `single` otherwise
*/
setFrequencyValue() {
const frequencyCheckbox = this.refs.form.querySelector("#monthly-checkbox");
if (frequencyCheckbox.checked) {
this.refs.form.querySelector("[name='frequency']").value = "monthly";
}
}

handleSubmit(event) {
event.preventDefault();
this.setFrequencyValue();
this.refs.form.submit();
if (!this.props.content.do_not_autoblock) {
this.props.onBlock();
}
}

renderDonations() {
const fieldNames = ["first", "second", "third", "fourth"];
const numberFormat = new Intl.NumberFormat(this.props.content.locale || navigator.language, {
style: "currency",
currency: this.props.content.currency_code,
minimumFractionDigits: 0,
});
// Default to `second` button
const {selected_button} = this.props.content;
const btnStyle = {
color: this.props.content.button_color,
backgroundColor: this.props.content.button_background_color,
};

return (<form className="EOYSnippetForm" action={this.props.content.donation_form_url} method={this.props.form_method} onSubmit={this.handleSubmit} ref="form">
{fieldNames.map((field, idx) => {
const button_name = `donation_amount_${field}`;
const amount = this.props.content[button_name];
return (<React.Fragment key={idx}>
<input type="radio" name="amount" value={amount} id={field} defaultChecked={button_name === selected_button} />
<label htmlFor={field} className="donation-amount">
{numberFormat.format(amount)}
</label>
</React.Fragment>);
})}

<div className="monthly-checkbox-container">
<input id="monthly-checkbox" type="checkbox" />
<label htmlFor="monthly-checkbox">
{this.props.content.monthly_checkbox_label_text}
</label>
</div>

<input type="hidden" name="frequency" value="single" />
<input type="hidden" name="currency" value={this.props.content.currency_code} />
<input type="hidden" name="presets" value={fieldNames.map(field => this.props.content[`donation_amount_${field}`])} />
<button style={btnStyle} type="submit" className="ASRouterButton donation-form-url">{this.props.content.button_label}</button>
</form>);
}

render() {
const textStyle = {
color: this.props.content.text_color,
backgroundColor: this.props.content.background_color,
};
const customElement = <em style={{backgroundColor: this.props.content.highlight_color}} />;
return (<SimpleSnippet {...this.props}
className={this.props.content.test}
customElements={{em: customElement}}
textStyle={textStyle}
extraContent={this.renderDonations()} />);
}
}
136 changes: 136 additions & 0 deletions content-src/asrouter/templates/EOYSnippet/EOYSnippet.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"title": "EOYSnippet",
"description": "Fundraising Snippet",
"version": "1.0.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": {
"donation_form_url": {
"type": "string",
"description": "Url to the donation form."
},
"currency_code": {
"type": "string",
"description": "The code for the currency. Examle gbp, cad, usd."
},
"locale": {
"type": "string",
"description": "String for the locale code."
},
"text": {
"allOf": [
{"$ref": "#/definitions/richText"},
{"description": "Main body text of snippet. HTML subset allowed: i, b, u, strong, em, br"}
]
},
"text_color": {
"type": "string",
"description": "Modify the text message color"
},
"background_color": {
"type": "string",
"description": "Snippet background color."
},
"highlight_color": {
"type": "string",
"description": "Paragraph em highlight color."
},
"donation_amount_first": {
"type": "number",
"description": "First button amount."
},
"donation_amount_second": {
"type": "number",
"description": "Second button amount."
},
"donation_amount_third": {
"type": "number",
"description": "Third button amount."
},
"donation_amount_fourth": {
"type": "number",
"description": "Fourth button amount."
},
"selected_button": {
"type": "string",
"description": "Default donation_amount_second. Donation amount button that's selected by default."
},
"icon": {
"type": "string",
"description": "Snippet icon. 64x64px. SVG or PNG preferred."
},
"title_icon": {
"type": "string",
"description": "Small icon that shows up before the title / text. 16x16px. SVG or PNG preferred. Grayscale."
},
"button_label": {
"allOf": [
{"$ref": "#/definitions/plainText"},
{"description": "Text for a button next to main snippet text that links to button_url. Requires button_url."}
]
},
"button_color": {
"type": "string",
"description": "The text color of the button. Valid CSS color."
},
"button_background_color": {
"type": "string",
"description": "The background color of the button. Valid CSS color."
},
"block_button_text": {
"type": "string",
"description": "Tooltip text used for dismiss button."
},
"monthly_checkbox_label_text": {
"type": "string",
"description": "Label text for monthly checkbox."
},
"test": {
"type": "string",
"description": "Different styles for the snippet. Options are bold and takeover."
},
"do_not_autoblock": {
"type": "boolean",
"description": "Used to prevent blocking the snippet after the CTA (link or button) has been clicked"
},
"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."
},
"args": {
"type": "string",
"description": "Additional parameters for link action, example which specific menu the button should open"
}
}
}
},
"additionalProperties": false,
"required": ["text", "donation_form_url", "donation_amount_first", "donation_amount_second", "donation_amount_third", "donation_amount_fourth", "button_label", "currency_code"],
"dependencies": {
"button_color": ["button_label"],
"button_background_color": ["button_label"]
}
}

50 changes: 50 additions & 0 deletions content-src/asrouter/templates/EOYSnippet/_EOYSnippet.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.EOYSnippetForm {
margin-top: 12px;
align-self: start;
font-size: 12px;
display: flex;
align-items: center;

.donation-amount,
.donation-form-url {
white-space: nowrap;
font-size: 14px;
padding: 5px 14px;
border-radius: 2px;
}

.donation-amount {
color: $grey-90;
margin-inline-end: 18px;
border: 1px solid $grey-40;
background: $grey-10;
cursor: pointer;
}

input {
&[type='radio'] {
opacity: 0;
margin-inline-end: -18px;

&:checked+.donation-amount {
background: $grey-50;
color: $white;
border: 1px solid $grey-60;
}
}
}

.monthly-checkbox-container {
width: 100%;
}

.donation-form-url {
margin-inline-start: 18px;
background-color: $snippets-donation-button-bg;
border: 0;
color: $white;
align-self: flex-end;
display: flex;
cursor: pointer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,20 @@ export class SimpleSnippet extends React.PureComponent {
renderText() {
const {props} = this;
return (<RichText text={props.content.text}
customElements={this.props.customElements}
localization_id="text"
links={props.content.links}
sendClick={props.sendClick} />);
}

render() {
const {props} = this;
const className = `SimpleSnippet${props.content.tall ? " tall" : ""}`;
return (<SnippetBase {...props} className={className}>
const className = `SimpleSnippet ${props.className}`;
return (<SnippetBase {...props} className={className} textStyle={this.props.textStyle}>
<img src={safeURI(props.content.icon) || DEFAULT_ICON_PATH} className="icon" />
<div>
{this.renderTitleIcon()} {this.renderTitle()} <p className="body">{this.renderText()}</p>
{this.props.extraContent}
</div>
{<div>{this.renderButton()}</div>}
</SnippetBase>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@
"type": "string",
"description": "Tooltip text used for dismiss button."
},
"tall": {
"type": "boolean",
"description": "To be used by fundraising only, increases height to roughly 120px. Defaults to false."
},
"do_not_autoblock": {
"type": "boolean",
"description": "Used to prevent blocking the snippet after the CTA (link or button) has been clicked"
Expand Down
Loading

0 comments on commit 45d8399

Please sign in to comment.