diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /browser/components/newtab/content-src/asrouter/templates/EOYSnippet | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/newtab/content-src/asrouter/templates/EOYSnippet')
3 files changed, 379 insertions, 0 deletions
diff --git a/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/EOYSnippet.jsx b/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/EOYSnippet.jsx new file mode 100644 index 0000000000..f324a69853 --- /dev/null +++ b/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/EOYSnippet.jsx @@ -0,0 +1,153 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import React from "react"; +import { SimpleSnippet } from "../SimpleSnippet/SimpleSnippet"; + +class EOYSnippetBase 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.props.sendClick(event); + this.setFrequencyValue(); + if (!this.props.content.do_not_autoblock) { + this.props.onBlock(); + } + this.refs.form.submit(); + } + + 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, + }; + const donationURLParams = []; + const paramsStartIndex = this.props.content.donation_form_url.indexOf("?"); + for (const entry of new URLSearchParams( + this.props.content.donation_form_url.slice(paramsStartIndex) + ).entries()) { + donationURLParams.push(entry); + } + + return ( + <form + className="EOYSnippetForm" + action={this.props.content.donation_form_url} + method={this.props.form_method} + onSubmit={this.handleSubmit} + data-metric="EOYSnippetForm" + ref="form" + > + {donationURLParams.map(([key, value], idx) => ( + <input type="hidden" name={key} value={value} key={idx} /> + ))} + {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 primary 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()} + /> + ); + } +} + +export const EOYSnippet = props => { + const extendedContent = { + monthly_checkbox_label_text: "Make my donation monthly", + locale: "en-US", + currency_code: "usd", + selected_button: "donation_amount_second", + ...props.content, + }; + + return ( + <EOYSnippetBase {...props} content={extendedContent} form_method="GET" /> + ); +}; diff --git a/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/EOYSnippet.schema.json b/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/EOYSnippet.schema.json new file mode 100644 index 0000000000..d9b6728067 --- /dev/null +++ b/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/EOYSnippet.schema.json @@ -0,0 +1,171 @@ +{ + "title": "EOYSnippet", + "description": "Fundraising Snippet", + "version": "1.1.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.", + "default": "usd" + }, + "locale": { + "type": "string", + "description": "String for the locale code.", + "default": "en-US" + }, + "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.", + "default": "donation_amount_second" + }, + "icon": { + "type": "string", + "description": "Snippet icon. 64x64px. SVG or PNG preferred." + }, + "icon_dark_theme": { + "type": "string", + "description": "Snippet icon. Dark theme variant. 64x64px. SVG or PNG preferred." + }, + "icon_alt_text": { + "type": "string", + "description": "Alt text for accessibility", + "default": "" + }, + "title": { + "allOf": [ + { "$ref": "#/definitions/plainText" }, + { "description": "Snippet title displayed before snippet text" } + ] + }, + "title_icon": { + "type": "string", + "description": "Small icon that shows up before the title / text. 16x16px. SVG or PNG preferred. Grayscale." + }, + "title_icon_dark_theme": { + "type": "string", + "description": "Small icon that shows up before the title / text. Dark theme variant. 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.", + "default": "Make my donation monthly" + }, + "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"] + } +} diff --git a/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/_EOYSnippet.scss b/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/_EOYSnippet.scss new file mode 100644 index 0000000000..d9911ff02c --- /dev/null +++ b/browser/components/newtab/content-src/asrouter/templates/EOYSnippet/_EOYSnippet.scss @@ -0,0 +1,55 @@ +.EOYSnippetForm { + margin: 10px 0 8px; + align-self: start; + font-size: 14px; + display: flex; + align-items: center; + + .donation-amount, + .donation-form-url { + white-space: nowrap; + font-size: 14px; + padding: 8px 20px; + border-radius: 2px; + } + + .donation-amount { + color: var(--newtab-text-primary-color); + margin-inline-end: 18px; + border: $input-border; + padding: 5px 14px; + background: var(--newtab-background-color-secondary); + cursor: pointer; + } + + input { + &[type='radio'] { + opacity: 0; + margin-inline-end: -18px; + + &:checked + .donation-amount { + // Use a text color for the background to achieve an inverted look. + background: var(--newtab-text-secondary-color); + color: var(--newtab-background-color-secondary); + border: $border-secondary; + } + + // accessibility + &:checked:focus + .donation-amount, + &:not(:checked):focus + .donation-amount { + border: 1px dotted var(--newtab-primary-action-background); + } + } + } + + .monthly-checkbox-container { + display: flex; + width: 100%; + } + + .donation-form-url { + margin-inline-start: 18px; + align-self: flex-end; + display: flex; + } +} |