From 020508efdb945aa252500f034a39c097127e1945 Mon Sep 17 00:00:00 2001 From: dkoo Date: Fri, 8 Dec 2023 13:32:40 -0700 Subject: [PATCH 001/243] feat: add support for order notes as a billing field --- .../readerRevenue/views/donation/index.tsx | 68 ++++++++++++------- .../wizards/class-reader-revenue-wizard.php | 12 +++- 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/assets/wizards/readerRevenue/views/donation/index.tsx b/assets/wizards/readerRevenue/views/donation/index.tsx index 03be8f4297..53825f5a22 100644 --- a/assets/wizards/readerRevenue/views/donation/index.tsx +++ b/assets/wizards/readerRevenue/views/donation/index.tsx @@ -2,7 +2,7 @@ * WordPress dependencies. */ import { useDispatch } from '@wordpress/data'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { ToggleControl, CheckboxControl } from '@wordpress/components'; /** @@ -41,6 +41,16 @@ const FREQUENCIES: { }; const FREQUENCY_SLUGS: FrequencySlug[] = Object.keys( FREQUENCIES ) as FrequencySlug[]; +type FieldConfig = { + autocomplete: string; + class: string[]; + label: string; + priority: number; + required: boolean; + type: string; + validate: string[]; +}; + type WizardData = { donation_data: | { errors: { [ key: string ]: string[] } } @@ -61,16 +71,9 @@ type WizardData = { status: string; }; available_billing_fields: { - [ key: string ]: { - autocomplete: string; - class: string[]; - label: string; - priority: number; - required: boolean; - type: string; - validate: string[]; - }; + [ key: string ]: FieldConfig; }; + order_notes_field: FieldConfig; }; export const DonationAmounts = () => { @@ -258,6 +261,8 @@ const BillingFields = () => { } ); const availableFields = wizardData.available_billing_fields; + const orderNotesField = wizardData.order_notes_field; + console.log( wizardData ); if ( ! availableFields || ! Object.keys( availableFields ).length ) { return null; } @@ -267,22 +272,23 @@ const BillingFields = () => { : Object.keys( availableFields ); return ( - <> - - - + + { Object.keys( availableFields ).map( fieldKey => ( { @@ -296,8 +302,23 @@ const BillingFields = () => { } } /> ) ) } + { orderNotesField && ( + { + let newFields = [ ...billingFields ]; + if ( billingFields.includes( 'order_comments' ) ) { + newFields = newFields.filter( field => field !== 'order_comments' ); + } else { + newFields = [ ...newFields, 'order_comments' ]; + } + changeHandler( [ 'billingFields' ] )( newFields ); + } } + /> + ) } - + ); }; @@ -347,6 +368,7 @@ const Donation = () => { ) } +
- -
-
-

- -

-

- -

+
+ +
From 26e2e6fa04d212e4f8f7192bfac9beb48ccdb6ac Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Thu, 14 Dec 2023 11:31:28 -0300 Subject: [PATCH 007/243] fix: interval reset --- assets/reader-activation/auth.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/assets/reader-activation/auth.js b/assets/reader-activation/auth.js index 2ba8286935..e951372b24 100644 --- a/assets/reader-activation/auth.js +++ b/assets/reader-activation/auth.js @@ -228,19 +228,18 @@ window.newspackRAS.push( function ( readerActivation ) { } ); } ); - let clearOtpTimerInterval; - function updateOTPTimer() { - if ( clearOtpTimerInterval ) { - clearOtpTimerInterval(); + let otpTimerInterval; + function resetOTPTimer() { + if ( otpTimerInterval ) { + clearInterval( otpTimerInterval ); } if ( ! resendCodeButton ) { return; } const otpTimer = localStorage.getItem( STORAGE_OTP_TIMER ); if ( otpTimer ) { - clearOtpTimerInterval = setInterval( () => { + otpTimerInterval = setInterval( () => { const timer = Math.floor( Date.now() / 1000 ) - parseInt( otpTimer ); - console.log( timer ); if ( timer < 60 ) { resendCodeButton.textContent = `Resend code in ${ 60 - timer } seconds`; resendCodeButton.disabled = true; @@ -248,13 +247,14 @@ window.newspackRAS.push( function ( readerActivation ) { resendCodeButton.textContent = 'Resend code'; resendCodeButton.disabled = false; localStorage.removeItem( STORAGE_OTP_TIMER ); + clearInterval( otpTimerInterval ); } }, 1000 ); } } if ( resendCodeButton ) { - updateOTPTimer(); + resetOTPTimer(); resendCodeButton.addEventListener( 'click', function ( ev ) { ev.preventDefault(); const body = new FormData(); @@ -289,7 +289,7 @@ window.newspackRAS.push( function ( readerActivation ) { console.log( { e } ); } ) .finally( () => { - updateOTPTimer(); + resetOTPTimer(); } ); } ); } ); @@ -485,7 +485,6 @@ window.newspackRAS.push( function ( readerActivation ) { form.endLoginFlow( data.message, 400 ); } ); } else { - console.log( { body } ); fetch( form.getAttribute( 'action' ) || window.location.pathname, { method: 'POST', headers: { @@ -515,7 +514,7 @@ window.newspackRAS.push( function ( readerActivation ) { if ( otpHash && [ 'register', 'link' ].includes( action ) ) { // Set OTP rate-limit timer localStorage.setItem( STORAGE_OTP_TIMER, Math.floor( Date.now() / 1000 ) ); - updateOTPTimer(); + resetOTPTimer(); if ( status === 200 ) { setFormAction( 'otp' ); } From 13013df7091e5429d66b507dbc3c4131c27e8740 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Thu, 14 Dec 2023 18:11:09 -0300 Subject: [PATCH 008/243] feat: resend code button tweaks --- assets/reader-activation/auth.js | 50 +++++++++++++------ assets/reader-activation/auth.scss | 2 - .../class-reader-activation.php | 45 ++++++++--------- 3 files changed, 55 insertions(+), 42 deletions(-) diff --git a/assets/reader-activation/auth.js b/assets/reader-activation/auth.js index e951372b24..b20f5cb488 100644 --- a/assets/reader-activation/auth.js +++ b/assets/reader-activation/auth.js @@ -27,6 +27,17 @@ function domReady( callback ) { document.addEventListener( 'DOMContentLoaded', callback ); } +/** + * Format time in MM:SS format. + * + * @param {number} time Time in seconds. + */ +function formatTime( time ) { + const minutes = Math.floor( time / 60 ); + const seconds = time % 60; + return `${ minutes }:${ seconds < 10 ? '0' : '' }${ seconds }`; +} + /** * Converts FormData into an object. * @@ -229,6 +240,7 @@ window.newspackRAS.push( function ( readerActivation ) { } ); let otpTimerInterval; + let otpOriginalButtonText; function resetOTPTimer() { if ( otpTimerInterval ) { clearInterval( otpTimerInterval ); @@ -236,26 +248,34 @@ window.newspackRAS.push( function ( readerActivation ) { if ( ! resendCodeButton ) { return; } + otpOriginalButtonText = resendCodeButton.textContent; + const updateButton = () => { + const timer = Math.floor( Date.now() / 1000 ) - parseInt( otpTimer ); + // Convert time to MM:SS format. + + if ( timer < 60 ) { + resendCodeButton.textContent = `${ otpOriginalButtonText } (${ formatTime( + 60 - timer + ) })`; + resendCodeButton.disabled = true; + } else { + resendCodeButton.textContent = otpOriginalButtonText; + resendCodeButton.disabled = false; + localStorage.removeItem( STORAGE_OTP_TIMER ); + clearInterval( otpTimerInterval ); + } + }; const otpTimer = localStorage.getItem( STORAGE_OTP_TIMER ); if ( otpTimer ) { - otpTimerInterval = setInterval( () => { - const timer = Math.floor( Date.now() / 1000 ) - parseInt( otpTimer ); - if ( timer < 60 ) { - resendCodeButton.textContent = `Resend code in ${ 60 - timer } seconds`; - resendCodeButton.disabled = true; - } else { - resendCodeButton.textContent = 'Resend code'; - resendCodeButton.disabled = false; - localStorage.removeItem( STORAGE_OTP_TIMER ); - clearInterval( otpTimerInterval ); - } - }, 1000 ); + otpTimerInterval = setInterval( updateButton, 1000 ); + updateButton(); } } if ( resendCodeButton ) { resetOTPTimer(); resendCodeButton.addEventListener( 'click', function ( ev ) { + messageContentElement.innerHTML = ''; ev.preventDefault(); const body = new FormData(); body.set( 'reader-activation-auth-form', 1 ); @@ -281,12 +301,12 @@ window.newspackRAS.push( function ( readerActivation ) { }, body, } ) - .then( res => { - console.log( res ); + .then( () => { + messageContentElement.innerHTML = newspack_reader_auth_labels.code_resent; localStorage.setItem( STORAGE_OTP_TIMER, Math.floor( Date.now() / 1000 ) ); } ) .catch( e => { - console.log( { e } ); + console.log( e ); } ) .finally( () => { resetOTPTimer(); diff --git a/assets/reader-activation/auth.scss b/assets/reader-activation/auth.scss index 43c33c75ab..ae7113eb75 100644 --- a/assets/reader-activation/auth.scss +++ b/assets/reader-activation/auth.scss @@ -340,8 +340,6 @@ } &__response { - font-size: 0.8125em; - line-height: 1.2307; &__content { p { margin: 0; diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index d486705413..3a3e6436f0 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -150,15 +150,13 @@ public static function enqueue_scripts() { NEWSPACK_PLUGIN_VERSION, true ); - \wp_localize_script( - self::AUTH_SCRIPT_HANDLE, - 'newspack_reader_auth_labels', - [ - 'invalid_email' => __( 'Please enter a valid email address.', 'newspack-plugin' ), - 'invalid_password' => __( 'Please enter a password.', 'newspack-plugin' ), - 'blocked_popup' => __( 'The popup has been blocked. Allow popups for the site and try again.', 'newspack-plugin' ), - ] - ); + $labels = [ + 'invalid_email' => __( 'Please enter a valid email address.', 'newspack-plugin' ), + 'invalid_password' => __( 'Please enter a password.', 'newspack-plugin' ), + 'blocked_popup' => __( 'The popup has been blocked. Allow popups for the site and try again.', 'newspack-plugin' ), + 'code_resent' => __( 'Code resent! Check your inbox.', 'newspack-plugin' ), + ]; + \wp_localize_script( self::AUTH_SCRIPT_HANDLE, 'newspack_reader_auth_labels', $labels ); \wp_script_add_data( self::AUTH_SCRIPT_HANDLE, 'async', true ); \wp_script_add_data( self::AUTH_SCRIPT_HANDLE, 'amp-plus', true ); \wp_enqueue_style( @@ -1092,19 +1090,6 @@ public static function render_auth_form( $is_inline = false ) {

-
- - - - - - -
- -

- -
-

@@ -1166,6 +1151,18 @@ function( $list ) {
+
+ +
+ +
+
+ +

+ +
+
+

-
- -
+
From 064a63a1052b82b14e7e41200cdc3f3b51b05625 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Mon, 18 Dec 2023 12:09:08 -0300 Subject: [PATCH 009/243] fix: move 3rd party auth --- .../class-reader-activation.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index d0fae8f0bc..3d970ed5e6 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -1090,6 +1090,9 @@ public static function render_auth_form( $is_inline = false ) {

+
+ +

@@ -1210,7 +1213,6 @@ function( $list ) {
-

@@ -1370,6 +1372,12 @@ public static function render_third_party_auth() { $classnames = implode( ' ', [ $class(), $class() . '--disabled' ] ); ?>

+
@@ -1377,12 +1385,6 @@ public static function render_third_party_auth() {
-
Date: Mon, 18 Dec 2023 12:11:44 -0300 Subject: [PATCH 010/243] feat: focus 1st input on OTP --- assets/reader-activation/auth.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assets/reader-activation/auth.js b/assets/reader-activation/auth.js index b20f5cb488..b9f3af12f1 100644 --- a/assets/reader-activation/auth.js +++ b/assets/reader-activation/auth.js @@ -353,6 +353,11 @@ window.newspackRAS.push( function ( readerActivation ) { emailAddressElements.forEach( element => { element.textContent = readerActivation.getReader()?.email || ''; } ); + // Focus on the first input. + const firstInput = container.querySelector( '.otp-field input[type="text"]' ); + if ( firstInput ) { + firstInput.focus(); + } } if ( [ 'link', 'pwd' ].includes( action ) ) { readerActivation.setAuthStrategy( action ); From fe3d62e1b38598cb348723f880d7014075c90708 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Mon, 18 Dec 2023 15:08:59 -0300 Subject: [PATCH 011/243] fix: move otp timer logic and handle disabled state --- assets/reader-activation/auth.js | 30 ++++++++----------- assets/reader-activation/auth.scss | 4 +++ assets/reader-activation/index.js | 26 ++++++++++++++++ .../class-reader-activation.php | 7 +++-- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/assets/reader-activation/auth.js b/assets/reader-activation/auth.js index b9f3af12f1..cdf0ec0aef 100644 --- a/assets/reader-activation/auth.js +++ b/assets/reader-activation/auth.js @@ -63,8 +63,6 @@ const convertFormDataToObject = ( formData, includedFields = [] ) => const SIGN_IN_MODAL_HASHES = [ 'signin_modal', 'register_modal' ]; -const STORAGE_OTP_TIMER = 'newspack_otp_timer'; - let currentHash; window.newspackRAS = window.newspackRAS || []; @@ -241,7 +239,7 @@ window.newspackRAS.push( function ( readerActivation ) { let otpTimerInterval; let otpOriginalButtonText; - function resetOTPTimer() { + function handleOTPTimer() { if ( otpTimerInterval ) { clearInterval( otpTimerInterval ); } @@ -250,38 +248,35 @@ window.newspackRAS.push( function ( readerActivation ) { } otpOriginalButtonText = resendCodeButton.textContent; const updateButton = () => { - const timer = Math.floor( Date.now() / 1000 ) - parseInt( otpTimer ); - // Convert time to MM:SS format. - - if ( timer < 60 ) { + const remaining = readerActivation.getOTPTimeRemaining(); + if ( remaining ) { resendCodeButton.textContent = `${ otpOriginalButtonText } (${ formatTime( - 60 - timer + remaining ) })`; resendCodeButton.disabled = true; } else { resendCodeButton.textContent = otpOriginalButtonText; resendCodeButton.disabled = false; - localStorage.removeItem( STORAGE_OTP_TIMER ); clearInterval( otpTimerInterval ); } }; - const otpTimer = localStorage.getItem( STORAGE_OTP_TIMER ); - if ( otpTimer ) { + const remaining = readerActivation.getOTPTimeRemaining(); + if ( remaining ) { otpTimerInterval = setInterval( updateButton, 1000 ); updateButton(); } } if ( resendCodeButton ) { - resetOTPTimer(); + handleOTPTimer(); resendCodeButton.addEventListener( 'click', function ( ev ) { messageContentElement.innerHTML = ''; ev.preventDefault(); + form.startLoginFlow(); const body = new FormData(); body.set( 'reader-activation-auth-form', 1 ); body.set( 'npe', emailInput.value ); body.set( 'action', 'link' ); - ev.preventDefault(); readerActivation .getCaptchaToken() .then( captchaToken => { @@ -303,13 +298,14 @@ window.newspackRAS.push( function ( readerActivation ) { } ) .then( () => { messageContentElement.innerHTML = newspack_reader_auth_labels.code_resent; - localStorage.setItem( STORAGE_OTP_TIMER, Math.floor( Date.now() / 1000 ) ); + readerActivation.setOTPTimer(); } ) .catch( e => { console.log( e ); } ) .finally( () => { - resetOTPTimer(); + handleOTPTimer(); + form.style.opacity = 1; } ); } ); } ); @@ -538,8 +534,8 @@ window.newspackRAS.push( function ( readerActivation ) { const otpHash = readerActivation.getOTPHash(); if ( otpHash && [ 'register', 'link' ].includes( action ) ) { // Set OTP rate-limit timer - localStorage.setItem( STORAGE_OTP_TIMER, Math.floor( Date.now() / 1000 ) ); - resetOTPTimer(); + readerActivation.setOTPTimer(); + handleOTPTimer(); if ( status === 200 ) { setFormAction( 'otp' ); } diff --git a/assets/reader-activation/auth.scss b/assets/reader-activation/auth.scss index ae7113eb75..c587c43477 100644 --- a/assets/reader-activation/auth.scss +++ b/assets/reader-activation/auth.scss @@ -159,6 +159,10 @@ border: 1px solid wp-colors.$gray-200; color: wp-colors.$gray-700; margin-bottom: 0.8rem; + &:disabled { + background-color: wp-colors.$gray-100; + color: wp-colors.$gray-600; + } &.back-button { border: 0; margin: 0; diff --git a/assets/reader-activation/index.js b/assets/reader-activation/index.js index a5343391e7..641e727589 100644 --- a/assets/reader-activation/index.js +++ b/assets/reader-activation/index.js @@ -144,6 +144,29 @@ export function getOTPHash() { return getCookie( 'np_otp_hash' ); } +const OTP_TIMER_STORAGE_KEY = 'newspack_otp_timer'; + +export function setOTPTimer() { + localStorage.setItem( OTP_TIMER_STORAGE_KEY, Math.floor( Date.now() / 1000 ) ); +} + +export function clearOTPTimer() { + localStorage.removeItem( OTP_TIMER_STORAGE_KEY ); +} + +export function getOTPTimeRemaining() { + const timer = localStorage.getItem( OTP_TIMER_STORAGE_KEY ); + if ( ! timer ) { + return 0; + } + const timeRemaining = + newspack_ras_config.otp_rate_interval - ( Math.floor( Date.now() / 1000 ) - timer ); + if ( ! timeRemaining ) { + clearOTPTimer(); + } + return timeRemaining > 0 ? timeRemaining : 0; +} + /** * Authenticate reader using an OTP code. * @@ -338,6 +361,9 @@ const readerActivation = { getReader, hasAuthLink, getOTPHash, + setOTPTimer, + clearOTPTimer, + getOTPTimeRemaining, authenticateOTP, setAuthStrategy, getAuthStrategy, diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index 3d970ed5e6..079346a395 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -114,6 +114,7 @@ public static function enqueue_scripts() { 'cid_cookie' => NEWSPACK_CLIENT_ID_COOKIE_NAME, 'authenticated_email' => $authenticated_email, 'otp_auth_action' => Magic_Link::OTP_AUTH_ACTION, + 'otp_rate_interval' => Magic_Link::RATE_INTERVAL, 'account_url' => function_exists( 'wc_get_account_endpoint_url' ) ? \wc_get_account_endpoint_url( 'dashboard' ) : '', ]; @@ -1078,6 +1079,9 @@ public static function render_auth_form( $is_inline = false ) {
+
+ +
@@ -1090,9 +1094,6 @@ public static function render_auth_form( $is_inline = false ) {

-
- -

From 391a9e5fcb80308cf49268aecbeb79640291cfb4 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Mon, 18 Dec 2023 15:12:39 -0300 Subject: [PATCH 012/243] chore: inline docs --- assets/reader-activation/index.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/assets/reader-activation/index.js b/assets/reader-activation/index.js index 641e727589..f439f072b0 100644 --- a/assets/reader-activation/index.js +++ b/assets/reader-activation/index.js @@ -144,16 +144,30 @@ export function getOTPHash() { return getCookie( 'np_otp_hash' ); } +/** + * OTP timer storage key. + */ const OTP_TIMER_STORAGE_KEY = 'newspack_otp_timer'; +/** + * Set the OTP timer to the current time. + */ export function setOTPTimer() { localStorage.setItem( OTP_TIMER_STORAGE_KEY, Math.floor( Date.now() / 1000 ) ); } +/** + * Clear the OTP timer. + */ export function clearOTPTimer() { localStorage.removeItem( OTP_TIMER_STORAGE_KEY ); } +/** + * Get the time remaining for the OTP timer. + * + * @return {number} Time remaining in seconds + */ export function getOTPTimeRemaining() { const timer = localStorage.getItem( OTP_TIMER_STORAGE_KEY ); if ( ! timer ) { From d952411d9e6e26727970c17ea3a007c3f3392920 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Mon, 18 Dec 2023 15:32:44 -0300 Subject: [PATCH 013/243] fix: move otp timer --- assets/reader-activation/auth.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/reader-activation/auth.js b/assets/reader-activation/auth.js index cdf0ec0aef..775323ba13 100644 --- a/assets/reader-activation/auth.js +++ b/assets/reader-activation/auth.js @@ -533,10 +533,10 @@ window.newspackRAS.push( function ( readerActivation ) { } const otpHash = readerActivation.getOTPHash(); if ( otpHash && [ 'register', 'link' ].includes( action ) ) { - // Set OTP rate-limit timer - readerActivation.setOTPTimer(); - handleOTPTimer(); if ( status === 200 ) { + // Set OTP rate-limit timer + readerActivation.setOTPTimer(); + handleOTPTimer(); setFormAction( 'otp' ); } /** If action is link, suppress message and status so the OTP handles it. */ From 2d64b1558e617ac79a4091f1390eb22060b83404 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Tue, 19 Dec 2023 09:30:36 -0300 Subject: [PATCH 014/243] Update includes/class-donations.php Co-authored-by: Derrick Koo --- includes/class-donations.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-donations.php b/includes/class-donations.php index cc50a0ef60..db1ea20baf 100644 --- a/includes/class-donations.php +++ b/includes/class-donations.php @@ -1069,7 +1069,7 @@ public static function disable_coupons( $enabled ) { */ public static function order_button_text( $text ) { if ( self::is_donation_cart() ) { - return __( 'Donate now', 'newspack-blocks' ); + return __( 'Donate now', 'newspack-plugin' ); } return $text; } From 6ff7dd04fba6ab130fba0bdf443bd03bf31e4219 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Tue, 19 Dec 2023 10:26:42 -0300 Subject: [PATCH 015/243] fix: support multiple price elements in the checkout ui --- .../class-woocommerce-cover-fees.php | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php index 1743794c9d..55da3fa5c6 100644 --- a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php +++ b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php @@ -13,9 +13,9 @@ * WooCommerce Order UTM class. */ class WooCommerce_Cover_Fees { - const CUSTOM_FIELD_NAME = 'newspack-wc-pay-fees'; - const PRICE_ELEMENT_ID = 'newspack-wc-price'; - const WC_ORDER_META_NAME = 'newspack_donor_covers_fees'; + const CUSTOM_FIELD_NAME = 'newspack-wc-pay-fees'; + const PRICE_ELEMENT_CLASS_NAME = 'newspack-wc-price'; + const WC_ORDER_META_NAME = 'newspack_donor_covers_fees'; /** * Initialize hooks. @@ -176,7 +176,7 @@ public static function amend_price_markup( $html, $price ) { if ( ! self::should_allow_covering_fees() ) { return $html; } - return str_replace( $price, '' . $price . '', $html ); + return str_replace( $price, '' . $price . '', $html ); } /** @@ -199,7 +199,10 @@ public static function print_checkout_helper_script() { // is not supported with coupons. $coupons_handling_script = 'setInterval(function(){ if(document.querySelector(".woocommerce-remove-coupon")){ - document.getElementById( "' . self::PRICE_ELEMENT_ID . '" ).textContent = "' . $original_price . '"; + var prices = document.querySelectorAll(".' . self::PRICE_ELEMENT_CLASS_NAME . '"); + for (var i = 0; i < prices.length; i++) { + prices[i].textContent = "' . $original_price . '"; + } } }, 1000);'; } @@ -208,15 +211,18 @@ public static function print_checkout_helper_script() { 'const form = document.querySelector(\'form[name="checkout"]\'); if ( form ) { form.addEventListener(\'change\', function( e ){ - const inputEl = document.getElementById( "' . self::CUSTOM_FIELD_NAME . '" ); - if( e.target.name === "payment_method" && e.target.value !== "stripe" && inputEl.checked ){ + var inputEl = document.getElementById( "' . self::CUSTOM_FIELD_NAME . '" ); + if( inputEl && e.target.name === "payment_method" && e.target.value !== "stripe" && inputEl.checked ){ inputEl.checked = false; newspackHandleCoverFees(inputEl); } }); } function newspackHandleCoverFees(inputEl) { - document.getElementById( "' . self::PRICE_ELEMENT_ID . '" ).textContent = inputEl.checked ? "' . $price_with_fee . '" : "' . $original_price . '"; + var prices = document.querySelectorAll(".' . self::PRICE_ELEMENT_CLASS_NAME . '"); + for (var i = 0; i < prices.length; i++) { + prices[i].textContent = inputEl.checked ? "' . $price_with_fee . '" : "' . $original_price . '"; + } };' . $coupons_handling_script ); } From d2b2f3bd2350ed04edf6a50e604c45cc4f5d26aa Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Tue, 19 Dec 2023 10:33:27 -0300 Subject: [PATCH 016/243] fix: use 'var' instead of 'const' --- .../reader-revenue/woocommerce/class-woocommerce-cover-fees.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php index 55da3fa5c6..3009f9267d 100644 --- a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php +++ b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php @@ -208,7 +208,7 @@ public static function print_checkout_helper_script() { } wp_add_inline_script( $handler, - 'const form = document.querySelector(\'form[name="checkout"]\'); + 'var form = document.querySelector(\'form[name="checkout"]\'); if ( form ) { form.addEventListener(\'change\', function( e ){ var inputEl = document.getElementById( "' . self::CUSTOM_FIELD_NAME . '" ); From 12e7c3913d7daa4f10d6957c0b6ee908599ebe51 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Tue, 19 Dec 2023 11:24:30 -0300 Subject: [PATCH 017/243] Revert "fix: use 'var' instead of 'const'" This reverts commit d2b2f3bd2350ed04edf6a50e604c45cc4f5d26aa. --- .../reader-revenue/woocommerce/class-woocommerce-cover-fees.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php index 3009f9267d..55da3fa5c6 100644 --- a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php +++ b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php @@ -208,7 +208,7 @@ public static function print_checkout_helper_script() { } wp_add_inline_script( $handler, - 'var form = document.querySelector(\'form[name="checkout"]\'); + 'const form = document.querySelector(\'form[name="checkout"]\'); if ( form ) { form.addEventListener(\'change\', function( e ){ var inputEl = document.getElementById( "' . self::CUSTOM_FIELD_NAME . '" ); From 1dcfd82d04755c5f781bc79195dfcd095f526ac9 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Tue, 19 Dec 2023 11:24:34 -0300 Subject: [PATCH 018/243] Revert "fix: support multiple price elements in the checkout ui" This reverts commit 6ff7dd04fba6ab130fba0bdf443bd03bf31e4219. --- .../class-woocommerce-cover-fees.php | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php index 55da3fa5c6..1743794c9d 100644 --- a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php +++ b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php @@ -13,9 +13,9 @@ * WooCommerce Order UTM class. */ class WooCommerce_Cover_Fees { - const CUSTOM_FIELD_NAME = 'newspack-wc-pay-fees'; - const PRICE_ELEMENT_CLASS_NAME = 'newspack-wc-price'; - const WC_ORDER_META_NAME = 'newspack_donor_covers_fees'; + const CUSTOM_FIELD_NAME = 'newspack-wc-pay-fees'; + const PRICE_ELEMENT_ID = 'newspack-wc-price'; + const WC_ORDER_META_NAME = 'newspack_donor_covers_fees'; /** * Initialize hooks. @@ -176,7 +176,7 @@ public static function amend_price_markup( $html, $price ) { if ( ! self::should_allow_covering_fees() ) { return $html; } - return str_replace( $price, '' . $price . '', $html ); + return str_replace( $price, '' . $price . '', $html ); } /** @@ -199,10 +199,7 @@ public static function print_checkout_helper_script() { // is not supported with coupons. $coupons_handling_script = 'setInterval(function(){ if(document.querySelector(".woocommerce-remove-coupon")){ - var prices = document.querySelectorAll(".' . self::PRICE_ELEMENT_CLASS_NAME . '"); - for (var i = 0; i < prices.length; i++) { - prices[i].textContent = "' . $original_price . '"; - } + document.getElementById( "' . self::PRICE_ELEMENT_ID . '" ).textContent = "' . $original_price . '"; } }, 1000);'; } @@ -211,18 +208,15 @@ public static function print_checkout_helper_script() { 'const form = document.querySelector(\'form[name="checkout"]\'); if ( form ) { form.addEventListener(\'change\', function( e ){ - var inputEl = document.getElementById( "' . self::CUSTOM_FIELD_NAME . '" ); - if( inputEl && e.target.name === "payment_method" && e.target.value !== "stripe" && inputEl.checked ){ + const inputEl = document.getElementById( "' . self::CUSTOM_FIELD_NAME . '" ); + if( e.target.name === "payment_method" && e.target.value !== "stripe" && inputEl.checked ){ inputEl.checked = false; newspackHandleCoverFees(inputEl); } }); } function newspackHandleCoverFees(inputEl) { - var prices = document.querySelectorAll(".' . self::PRICE_ELEMENT_CLASS_NAME . '"); - for (var i = 0; i < prices.length; i++) { - prices[i].textContent = inputEl.checked ? "' . $price_with_fee . '" : "' . $original_price . '"; - } + document.getElementById( "' . self::PRICE_ELEMENT_ID . '" ).textContent = inputEl.checked ? "' . $price_with_fee . '" : "' . $original_price . '"; };' . $coupons_handling_script ); } From b0c4828c2869456a01d0a9f37468573a2c778ceb Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Wed, 20 Dec 2023 14:22:09 -0300 Subject: [PATCH 019/243] fix: prevent warning on coupon filter --- includes/class-donations.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/includes/class-donations.php b/includes/class-donations.php index db1ea20baf..25a18e4fff 100644 --- a/includes/class-donations.php +++ b/includes/class-donations.php @@ -1052,6 +1052,9 @@ public static function update_billing_fields( $billing_fields ) { * @return bool */ public static function disable_coupons( $enabled ) { + if ( is_admin() ) { + return $enabled; + } $cart = WC()->cart; if ( ! $cart ) { return $enabled; From 690cc732637f5e91d804d1b8118dab35e8e9ca23 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Wed, 20 Dec 2023 15:27:29 -0300 Subject: [PATCH 020/243] fix: reenable submit buttons --- assets/reader-activation/auth.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/reader-activation/auth.js b/assets/reader-activation/auth.js index 775323ba13..6287e4ee67 100644 --- a/assets/reader-activation/auth.js +++ b/assets/reader-activation/auth.js @@ -306,6 +306,9 @@ window.newspackRAS.push( function ( readerActivation ) { .finally( () => { handleOTPTimer(); form.style.opacity = 1; + submitButtons.forEach( button => { + button.disabled = false; + } ); } ); } ); } ); From bbd0aa42ff51005055f79972c0cae755fa250d4c Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Thu, 14 Dec 2023 17:21:04 -0800 Subject: [PATCH 021/243] feat: start building out Newspack UI styles. --- assets/blocks/reader-registration/style.scss | 19 - assets/newspack-ui/index.js | 1 + assets/newspack-ui/scss/_modals.scss | 77 +++ assets/newspack-ui/scss/elements/_boxes.scss | 46 ++ assets/newspack-ui/scss/elements/_icons.scss | 27 + assets/newspack-ui/scss/elements/_index.scss | 25 + assets/newspack-ui/scss/elements/_tables.scss | 30 ++ .../scss/elements/_typography.scss | 20 + .../scss/elements/forms/_buttons.scss | 73 +++ .../scss/elements/forms/_checkbox-radio.scss | 71 +++ .../scss/elements/forms/_index.scss | 32 ++ .../scss/elements/forms/_labels.scss | 38 ++ .../scss/elements/forms/_text-inputs.scss | 38 ++ .../newspack-ui/scss/variables/_colors.scss | 48 ++ assets/newspack-ui/scss/variables/_fonts.scss | 17 + assets/newspack-ui/scss/variables/_index.scss | 16 + .../newspack-ui/scss/variables/_spacing.scss | 12 + assets/newspack-ui/style.scss | 35 ++ assets/reader-activation/auth.scss | 77 +-- includes/class-newspack-ui.php | 491 ++++++++++++++++++ includes/class-newspack.php | 3 + .../class-reader-activation.php | 39 +- webpack.config.js | 6 + 23 files changed, 1140 insertions(+), 101 deletions(-) create mode 100644 assets/newspack-ui/index.js create mode 100644 assets/newspack-ui/scss/_modals.scss create mode 100644 assets/newspack-ui/scss/elements/_boxes.scss create mode 100644 assets/newspack-ui/scss/elements/_icons.scss create mode 100644 assets/newspack-ui/scss/elements/_index.scss create mode 100644 assets/newspack-ui/scss/elements/_tables.scss create mode 100644 assets/newspack-ui/scss/elements/_typography.scss create mode 100644 assets/newspack-ui/scss/elements/forms/_buttons.scss create mode 100644 assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss create mode 100644 assets/newspack-ui/scss/elements/forms/_index.scss create mode 100644 assets/newspack-ui/scss/elements/forms/_labels.scss create mode 100644 assets/newspack-ui/scss/elements/forms/_text-inputs.scss create mode 100644 assets/newspack-ui/scss/variables/_colors.scss create mode 100644 assets/newspack-ui/scss/variables/_fonts.scss create mode 100644 assets/newspack-ui/scss/variables/_index.scss create mode 100644 assets/newspack-ui/scss/variables/_spacing.scss create mode 100644 assets/newspack-ui/style.scss create mode 100644 includes/class-newspack-ui.php diff --git a/assets/blocks/reader-registration/style.scss b/assets/blocks/reader-registration/style.scss index 4501c1561d..0f49612c04 100644 --- a/assets/blocks/reader-registration/style.scss +++ b/assets/blocks/reader-registration/style.scss @@ -110,25 +110,6 @@ } } - &__have-account { - background-color: #111; - padding: 4px 15px; - margin-bottom: 15px; - text-align: center; - margin-top: 20px; - @media screen and ( min-width: 600px ) { - margin-top: 0; - } - &, - a { - color: #fff !important; - } - a:active, - a:hover { - color: #d6d6d6 !important; - } - } - &__help-text { p { color: wp-colors.$gray-700; diff --git a/assets/newspack-ui/index.js b/assets/newspack-ui/index.js new file mode 100644 index 0000000000..423b033ce7 --- /dev/null +++ b/assets/newspack-ui/index.js @@ -0,0 +1 @@ +import './style.scss'; diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss new file mode 100644 index 0000000000..e7ab6cbb9c --- /dev/null +++ b/assets/newspack-ui/scss/_modals.scss @@ -0,0 +1,77 @@ +.newspack-ui { + &__modal { + background: var( --newspack-ui-color-body-bg ); + border-radius: var( --newspack-ui-border-radius ); + max-width: var( --newspack-ui-modal-width-medium ); + overflow: hidden; + + // Modal header & footer + &__header, + &__footer, { + padding: var( --newspack-ui-spacer-4 ) var( --newspack-ui-spacer-5 ); + } + + &__header { + align-items: center; + border-bottom: 1px solid var( --newspack-ui-color-border ); + display: flex; + justify-content: space-between; + + h2 { + font-size: var( --newspack-ui-font-size-medium ); + margin: 0; + } + + button { // Close button + background: transparent; + border: 0; + color: var( --newspack-ui-color-text-high-contrast ); + cursor: pointer; + margin: -8px; + padding: 8px; + + &:focus, + &:hover { + background: transparent; + color: var( --newspack-ui-color-text-med-contrast ); + } + svg { + display: block; + } + } + } + + &__content { + backface-visibility: visible; + padding: var( --newspack-ui-spacer-5 ); + } + + &__footer { + background: var( --newspack-ui-color-gray-100 ); + color: var( --newspack-ui-color-text-med-contrast ); + font-size: var( --newspack-ui-font-size-small ); + line-height: var( --newspack-ui-line-height-small ); + } + + // Narrow modal + &__small { + max-width: var( --newspack-ui-modal-width-small ); + } + + // Contents + h3 { + font-size: var( --newspack-ui-font-size-medium ); + } + + &__footer, + &__content { + > *:first-child { + margin-top: 0; + } + + > *:last-child { + margin-bottom: 0; + } + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/_boxes.scss b/assets/newspack-ui/scss/elements/_boxes.scss new file mode 100644 index 0000000000..a6382d3249 --- /dev/null +++ b/assets/newspack-ui/scss/elements/_boxes.scss @@ -0,0 +1,46 @@ +.newspack-ui { + .newspack-ui { + &__box { + background: var( --newspack-ui-color-gray-100 ); + border-radius: var( --newspack-ui-border-radius ); + margin-bottom: var( --newspack-ui-spacer-5 ); + padding: var( --newspack-ui-spacer-5 ); + + // Backgrounds & Borders + &__success { + background: var( --newspack-ui-color-alert-green-bg ); + } + + &__error { + background: var( --newspack-ui-color-alert-red-bg ); + } + + &__warning { + // TODO + } + + &__border { + background: transparent; + border: 1px solid var( --newspack-ui-color-border ); + } + + // Text alignments + &__text-center { + text-align: center; + } + + // Some style resets. + h2 { + font-size: 1em; + } + + > *:first-child { + margin-top: 0; + } + + > *:last-child { + margin-bottom: 0; + } + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/_icons.scss b/assets/newspack-ui/scss/elements/_icons.scss new file mode 100644 index 0000000000..5875723f76 --- /dev/null +++ b/assets/newspack-ui/scss/elements/_icons.scss @@ -0,0 +1,27 @@ +// Thank you SVG +.newspack-ui { + &__icon { + align-items: center; + border-radius: 100%; + display: flex; + height: var( --newspack-ui-spacer-7 ); + justify-content:center; + margin: 0 auto var( --newspack-ui-spacer-2 ); + width: var( --newspack-ui-spacer-7 ); + + &__success { + background: var( --newspack-ui-color-alert-green ); + color: var( --newspack-ui-color-body-bg ); + } + + &__error { + background: var( --newspack-ui-color-alert-red ); + color: var( --newspack-ui-color-body-bg ); + } + + &__warning { + background: var( --newspack-ui-color-alert-yellow ); + color: var( --newspack-ui-color-body-bg ); + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/_index.scss b/assets/newspack-ui/scss/elements/_index.scss new file mode 100644 index 0000000000..f974481509 --- /dev/null +++ b/assets/newspack-ui/scss/elements/_index.scss @@ -0,0 +1,25 @@ +@use 'boxes'; +@use 'forms'; +@use 'icons'; +@use 'tables'; +@use 'typography'; + +// TODO: Find a better home for this: +.newspack-ui { + &__word-divider { + align-items: center; + display: flex; + font-size: var( --newspack-ui-font-size-small ); + gap: var( --newspack-ui-spacer-2 ); + justify-content: space-evenly; + margin: var( --newspack-ui-spacer-5 ) 0; + + &::before, + &::after { + border-top: 1px solid var( --newspack-ui-color-border ); + content: ''; + display: block; + width: 100%; + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/_tables.scss b/assets/newspack-ui/scss/elements/_tables.scss new file mode 100644 index 0000000000..5210b5010e --- /dev/null +++ b/assets/newspack-ui/scss/elements/_tables.scss @@ -0,0 +1,30 @@ +.newspack-ui { + table { + border: 0; + font-size: var( --newspack-ui-font-size-small ); // Prevent relative font size + line-height: var( --newspack-ui-line-height-large ); + margin: calc( var( --newspack-ui-spacer-1 ) / -2 ) 0; // Offset cell padding. + th, + td { + background: transparent; + border-color: var( --newspack-ui-color-border ); + border-width: 0 0 1px; + font-size: var( --newspack-ui-font-size-small ); // Prevent relative font size + padding: calc( var( --newspack-ui-spacer-1 ) / 2 ) 0; + vertical-align: top; + > * { + white-space: nowrap; + } + } + th { + font-weight: 600; + text-align: left; + } + tfoot tr:last-child { + th, + td { + border-bottom: 0; + } + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/_typography.scss b/assets/newspack-ui/scss/elements/_typography.scss new file mode 100644 index 0000000000..01a65e7f9f --- /dev/null +++ b/assets/newspack-ui/scss/elements/_typography.scss @@ -0,0 +1,20 @@ +.newspack-ui { + -webkit-font-smoothing: antialiased; + + p { + margin: var( --newspack-ui-spacer-2 ) 0; + } + + strong, + &__font__bold { + font-weight: var( --newspack-ui-font-weight-strong ); + } + + &__font__normal { + font-weight: normal; + } + + &__font__small { + font-size: var( --newspack-ui-font-size-small ); + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss new file mode 100644 index 0000000000..16ce1a83e7 --- /dev/null +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -0,0 +1,73 @@ +.newspack-ui { + // TODO: define some kind of size hierachy for buttons eg. small, medium, large; + // not needed for RAS, but likely for My Account. + .button, + button, + input[type='button'], + input[type='reset'], + input[type='submit'] { + align-items: center; + border: 0; + border-radius: var( --newspack-ui-border-radius-small ); + display: inline-flex; + font-family: var( --newspack-ui-font-family); + font-size: var( --newspack-ui-font-size-small ); + font-weight: 600; + gap: var( --newspack-ui-spacer-2 ); + justify-content: center; + line-height: var( --newspack-ui-line-height-large ); + margin-bottom: var( --newspack-ui-spacer-1 ); + padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-3 ); // TODO: correct this + transition: background-color 150ms ease-in-out; + + &:hover { + // TODO + } + + &:focus { + // TODO + } + + &:disabled { + background: var( --newspack-ui-color-gray-100 ) !important; + color: var( --newspack-ui-color-text-med-contrast ) !important; + cursor: default; + } + + &.newspack-ui__button{ + &__wide { + display: flex; + width: 100%; + } + + &__primary { + background: var( --newspack-ui-color-button-bg ); + color: var( --newspack-ui-color-button-text ); + + &:hover { + background: var( --newspack-ui-color-button-bg-hover ); + } + } + + &__secondary { + background: transparent; + border: 1px solid var( --newspack-ui-color-border ); + color: var( --newspack-ui-color-text-high-contrast ); + padding: calc( var( --newspack-ui-spacer-2 ) - 1px ) calc( var( --newspack-ui-spacer-3 ) - 1px ); + + &:hover { + background: var( --newspack-ui-color-gray-100 ); + } + } + + &__tertiary { + background: transparent; + color: var( --newspack-ui-color-text-high-contrast ); + + &:hover { + background: var( --newspack-ui-color-gray-100 ); + } + } + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss new file mode 100644 index 0000000000..32ad405ed9 --- /dev/null +++ b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss @@ -0,0 +1,71 @@ +.newspack-ui { + input[type='checkbox'], + input[type='radio'] { + appearance: none; + background: white; + border: solid 1px var( --newspack-ui-color-border ); + color: white; + cursor: pointer; + display: inline-grid; + font: inherit; + height: var( --newspack-ui-spacer-5 ) !important; + margin: 0; + place-content: center; + width: var( --newspack-ui-spacer-5 ) !important; + + &::before { + content: ''; + display: block; + opacity: 0; + } + + &:checked { + &::before { + opacity: 1; + } + } + + &:focus { + outline: 1.5px solid var( --newspack-ui-color-radio-bg ); + outline-offset: 1px; + } + + &:disabled { + cursor: not-allowed; + opacity: 0.75; + } + } + + input[type='checkbox'] { + border-radius: var( --newspack-ui-border-radius ); + + &::before { + background: transparent + url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath d='M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z' fill='white'%3E%3C/path%3E%3C/svg%3E" ) + 0 0 no-repeat; + height: var( --newspack-ui-spacer-5 ); + width: var( --newspack-ui-spacer-5 ); + } + + &:checked { + background: var( --newspack-ui-color-radio-bg ); + border-color: transparent; + } + } + + input[type='radio'] { + border-radius: 100%; + + &::before { + background: var( --newspack-ui-color-radio-bg ); + border-radius: 100%; + height: var( --newspack-ui-spacer-3 ); + margin: 4px; + width: var( --newspack-ui-spacer-3 ); + } + + &:checked { + border-color: var( --newspack-ui-color-radio-bg ); + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss new file mode 100644 index 0000000000..704f7ff58d --- /dev/null +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -0,0 +1,32 @@ +@use 'buttons'; +@use 'checkbox-radio'; +@use 'labels'; +@use 'text-inputs'; + +// TODO: Find a better home for this stuff. +.newspack-ui { + form { + > *:last-child { + margin-bottom: 0; + } + } + + select { + font-family: var( --newspack-ui-font-family); + line-height: var( --newspack-ui-line-height-large ); + } + + // Container for displaying grid of inputs. + & &__code-input { + display: flex; + gap: var( --newspack-ui-spacer-1 ); + } + + // Container for input description. + &__field-description { + display: block; + font-size: var( --newspack-ui-font-size-small ); + line-height: var( --newspack-ui-line-height-small ); + margin: var( --newspack-ui-spacer-1 ) 0 var( --newspack-ui-spacer-5 ); + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss new file mode 100644 index 0000000000..de18d6b9cc --- /dev/null +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -0,0 +1,38 @@ +.newspack-ui { + // TODO: In the current My Account mockups, these are 16px. + label { + display: block; + font-family: var( --newspack-ui-font-family); + font-size: var( --newspack-ui-font-size-small ) !important; // !important to override Newspack Theme. + font-weight: 600; + line-height: var( --newspack-ui-line-height-small ); + margin: 0 0 var( --newspack-ui-spacer-1 ); + + // For labels containing radio, checkbox inputs: + &.newspack-ui__input-checkradio { // For Firefox; otherwise could use &:has( input[type='checkbox'] ),&:has( input[type='radio'] ) + align-items: center; + display: flex; + gap: var( --newspack-ui-spacer-2 ); + + // For creating a bordered 'list' of radio, checkbox inputs: + &.newspack-ui__input-list { + align-items: flex-start; + border: 1px solid var( --newspack-ui-color-border ); + border-radius: var( --newspack-ui-border-radius ); + font-weight: normal; + margin-bottom: var( --newspack-ui-spacer-5 ); + padding: var( --newspack-ui-spacer-3 ); + + // This selector isn't supported in Firefox yet. + &:has( input:checked ) { + background: var( --newspack-ui-color-primary-000 ); + border-color: var( --newspack-ui-color-primary-500 ); + } + + + .newspack-ui__input-list { + margin-top: calc( var( --newspack-ui-spacer-2 ) * -1 ); + } + } + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/forms/_text-inputs.scss b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss new file mode 100644 index 0000000000..32614db5df --- /dev/null +++ b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss @@ -0,0 +1,38 @@ +.newspack-ui { + // TODO: define some kind of size hierachy for buttons eg. small, medium, large; + // not needed for RAS, but likely for My Account. + input[type='text'], + input[type='email'], + input[type='url'], + input[type='password'], + input[type='search'], + input[type='number'], + input[type='tel'], + input[type='range'], + input[type='date'], + input[type='month'], + input[type='week'], + input[type='time'], + input[type='datetime'], + input[type='datetime-local'], + input[type='zip'], + input[type='color'], + textarea { + border-color: var( --newspack-ui-color-border ); + border-radius: var( --newspack-ui-border-radius ); + display: block; + font-family: var( --newspack-ui-font-family); + font-size: var( --newspack-ui-font-size-small ); + line-height: var( --newspack-ui-line-height-large ); + padding: calc( var( --newspack-ui-spacer-2 ) - 1px ) calc( var( --newspack-ui-spacer-3 ) - 1px ); + width: 100%; + + &:focus { + border-color: var( --newspack-ui-color-text-med-contrast ); + } + + &:disabled { + // TODO. + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/variables/_colors.scss b/assets/newspack-ui/scss/variables/_colors.scss new file mode 100644 index 0000000000..c18b13b7ef --- /dev/null +++ b/assets/newspack-ui/scss/variables/_colors.scss @@ -0,0 +1,48 @@ +:root { + // Newspack Blues + --newspack-ui-color-primary-000: #f5fdff; + --newspack-ui-color-primary-050: #d6f6ff; + --newspack-ui-color-primary-100: #b4e4ff; + --newspack-ui-color-primary-200: #93ccfd; + --newspack-ui-color-primary-300: #72affb; + --newspack-ui-color-primary-400: #528dfc; + --newspack-ui-color-primary-500: #36f; + --newspack-ui-color-primary-600: #2240d5; + --newspack-ui-color-primary-700: #1522af; + --newspack-ui-color-primary-800: #0b0b8d; + --newspack-ui-color-primary-900: #0d046e; + --newspack-ui-color-primary-950: #0e0052; + + // Grays - notes from the Gutenberg styles. + // TODO: Import from 'wordpress/base-styles/colors' ? + --newspack-ui-color-black: #000; // Use only when you truly need pure black. For UI, use $gray-900. + --newspack-ui-color-gray-900: #1e1e1e; + --newspack-ui-color-gray-800: #2f2f2f; + --newspack-ui-color-gray-700: #757575; // Meets 4.6:1 text contrast against white. + --newspack-ui-color-gray-600: #949494; // Meets 3:1 UI or large text contrast against white. + --newspack-ui-color-gray-400: #ccc; + --newspack-ui-color-gray-300: #ddd; // Used for most borders. + --newspack-ui-color-gray-200: #e0e0e0; // Used sparingly for light borders. + --newspack-ui-color-gray-100: #f0f0f0; // Used for light gray backgrounds. + --newspack-ui-color-white: #fff; + + // Alert colors + --newpsack-ui-color-alert-yellow: #f0b849; + --newspack-ui-color-alert-green: #4ab866; + --newspack-ui-color-alert-red: #cc1818; + // --newpsack-ui-color-alert-yellow-bg: TBD + --newspack-ui-color-alert-green-bg: #edfaef; + --newpsack-ui-color-alert-red-bg: #fcf0f1; + + // Specific assignments - general: + --newspack-ui-color-text-high-contrast: var( --newspack-ui-color-gray-900 ); + --newspack-ui-color-text-med-contrast: var( --newspack-ui-color-gray-700 ); + --newspack-ui-color-border: var( --newspack-ui-color-gray-300 ); + --newspack-ui-color-body-bg: var( --newspack-ui-color-white ); + + // Specific assignments - form elements + --newspack-ui-color-button-bg: var( --newspack-ui-color-gray-900 ); + --newspack-ui-color-button-bg-hover: var( --newspack-ui-color-gray-800 ); // TODO: Replace w/correct value. + --newspack-ui-color-button-text: var( --newspack-ui-color-white ); + --newspack-ui-color-radio-bg: var( --newspack-ui-color-gray-900 ); +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/variables/_fonts.scss b/assets/newspack-ui/scss/variables/_fonts.scss new file mode 100644 index 0000000000..3ad47f8291 --- /dev/null +++ b/assets/newspack-ui/scss/variables/_fonts.scss @@ -0,0 +1,17 @@ +:root { + // Fonts + --newspack-ui-font-family: system-ui, sans-serif; + + // TODO: the base size for the modals is 16px, with small text/labels at 14px; + // The My Account designs appear to use 16px for most labels + // Should we have a in-modal vs. non-modal set of font sizes? + --newspack-ui-font-size-large: 20px; + --newspack-ui-font-size-medium: 16px; // modal baseline + --newspack-ui-font-size-small: 14px; // modal small + --newspack-ui-font-weight-strong: 600; + + // Line heights - TODO: sort this out: + --newspack-ui-line-height-large: 1.7143; // inputs, buttons + --newspack-ui-line-height-medium: 1.5; // 16px font size + --newspack-ui-line-height-small: 1.4286; // 14px font sizes +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/variables/_index.scss b/assets/newspack-ui/scss/variables/_index.scss new file mode 100644 index 0000000000..a4cb983f00 --- /dev/null +++ b/assets/newspack-ui/scss/variables/_index.scss @@ -0,0 +1,16 @@ +@use 'colors'; +@use 'fonts'; +@use 'spacing'; + +// TODO: Some misc styles that need a home! +:root { + // Modal widths + --newspack-ui-modal-width-large: 964px; + --newspack-ui-modal-width-medium: 600px; + --newspack-ui-modal-width-small: 368px; + + // Border radius - not ems because the font size of the element itself caused a cascade. + --newspack-ui-border-radius: 6px; + --newspack-ui-border-radius-small: 5px; + +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/variables/_spacing.scss b/assets/newspack-ui/scss/variables/_spacing.scss new file mode 100644 index 0000000000..64934b7204 --- /dev/null +++ b/assets/newspack-ui/scss/variables/_spacing.scss @@ -0,0 +1,12 @@ +:root { + // Spacing - not ems because the font size of the element itself caused a cascade + --newspack-ui-spacer-1: 8px; + --newspack-ui-spacer-2: calc( var( --newspack-ui-spacer-1 ) * 1.5 ); // 12px + --newspack-ui-spacer-3: calc( var( --newspack-ui-spacer-1 ) * 2 ); // 16px + --newspack-ui-spacer-4: calc( var( --newspack-ui-spacer-1 ) * 2.5 ); // 20px + --newspack-ui-spacer-5: calc( var( --newspack-ui-spacer-1 ) * 3 ); // 24px + --newspack-ui-spacer-6: calc( var( --newspack-ui-spacer-1 ) * 4 ); // 32px - TODO: clamp? + --newspack-ui-spacer-7: calc( var( --newspack-ui-spacer-1 ) * 5 ); // 40px - TODO: clamp? + --newspack-ui-spacer-8: calc( var( --newspack-ui-spacer-1 ) * 6 ); // 48px - TODO: clamp? + --newspack-ui-spacer-9: calc( var( --newspack-ui-spacer-1 ) * 8 ); // 64px - TODO: clamp? +} \ No newline at end of file diff --git a/assets/newspack-ui/style.scss b/assets/newspack-ui/style.scss new file mode 100644 index 0000000000..68fce49d5a --- /dev/null +++ b/assets/newspack-ui/style.scss @@ -0,0 +1,35 @@ +@use 'scss/variables'; +@use 'scss/elements'; +@use 'scss/modals'; + +.newspack-ui { + font-family: var( --newspack-ui-font-family ); + font-size: var( --newspack-ui-font-size-medium ) !important; + + // Need better spot for this + &__color-text-gray { + color: var( --newspack-ui-color-text-med-contrast ); + } + + // Overrides for theme styles -- to move to theme? + h2, + h3 { + font-size: var( --newspack-ui-font-size-medium ); + } + + a, + a:hover { + color: inherit !important; + } + + // TODO: This specifically is a WooCommerce HTML structure; have been using it for other elements so far, but do we want to? + form p { + margin: 0 0 var( --newspack-ui-spacer-5 ); + } + + .newspack-ui__modal__small { + form p { + margin: 0 0 var( --newspack-ui-spacer-2 ); + } + } +} diff --git a/assets/reader-activation/auth.scss b/assets/reader-activation/auth.scss index c587c43477..bbf6a2356b 100644 --- a/assets/reader-activation/auth.scss +++ b/assets/reader-activation/auth.scss @@ -81,6 +81,10 @@ z-index: auto; } + &__have-account { + flex: 1 1 100%; + } + .nphp, input[type='email'].nphp { @include mixins.visuallyHidden; @@ -179,7 +183,6 @@ flex: 1 1 100%; font-size: 1rem; margin: 0; - button[type='submit'] { background-color: var( --newspack-cta-color ); color: var( --newspack-cta-contrast-color ); @@ -223,26 +226,6 @@ overflow-y: hidden; } } - &__have-account { - background-color: #111; - padding: 4px 15px; - margin-bottom: 11px; - padding-top: 6px !important; - padding-bottom: 8px !important; - text-align: center; - width: calc( 100% - 37px ); - @media screen and ( min-width: 600px ) { - width: 100%; - } - &, - a { - color: #fff; - } - a:active, - a:hover { - color: #d6d6d6; - } - } &__header { align-items: baseline; @@ -288,16 +271,6 @@ } &__content { - padding: 16px; - - @media screen and ( min-width: 600px ) { - padding: 32px; - } - - @media screen and ( min-width: 782px ) { - padding: 47px 64px 64px; - } - form { transition: opacity 0.2s ease-in-out; @@ -354,48 +327,6 @@ } } - &__close { - align-items: center; - background: white; - border: none; - border-radius: 3px; - box-shadow: none; - color: inherit; - cursor: pointer; - display: flex; - font-size: inherit; - height: 40px; - justify-content: center; - margin: 8px; - padding: 0; - position: absolute; - right: 0; - top: 7px; - width: 40px; - - @media screen and ( min-width: 600px ) { - height: 30px; - margin: 2px; - width: 30px; - } - - @media screen and ( min-width: 782px ) { - height: 48px; - margin: 8px; - width: 48px; - } - - svg { - fill: currentcolor; - flex: 0 0 24px; - } - - &:focus { - outline: 1.5px solid #111; - outline-offset: 2px; - } - } - &__terms-text { color: wp-colors.$gray-700; font-size: 0.8125em; diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php new file mode 100644 index 0000000000..8d6d57ab9f --- /dev/null +++ b/includes/class-newspack-ui.php @@ -0,0 +1,491 @@ + +
+

Temporary Razzak Component Demo

+ +

Regular text (16px)

+ +

Small text (14px).

+ +
+ +

Boxes

+ +
+

Default box style

+
+ +
+

Border box style

+
+ +
+

"Success" box style

+
+ +
+ + + + + +

+ Success box style, plus icon + newspack-ui__box__text-center class. +

+ +

Plus a little bit of text below it.

+
+ +
+ +

Form elements

+ +

+ + +

+ +

+ + +

+ + +

+ +

+ +

+ +

+ +

+ +

+ + +
+ +

Checkbox/Radio Lists

+ + + +
+ + + + +
+ +

Order table

+

Transaction details

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProductSubtotal
+ Donate: Yearly  × 1 + + $180.00 / year +
Subtotal$180.00
GST 5%)$9.00
PST (7%)$12.60
Total$201.60
+
+ +
+ +

Buttons

+

newspack-ui__button__primary, __secondary, and __tertiary classes for colours/borders, and newspack-ui__button__widefor being 100% wide

+
+
+
+
+
+ + + + + + + + +
+ +

Modals

+ +
+ +
+
+

This is a header

+ +
+ +
+

This is the modal content

+
+ +
+

This is the modal footer.

+
+
+
+ +

Small size

+ +
+
+
+

Auth Modal Contents Default

+ + +
+ +
+ + + +
+ Or +
+ +
+

+ + +

+ + + +
+
+ +
+

This is the modal footer.

+
+
+
+ +
+
+
+

Auth Modal Contents OTP

+ + +
+ +
+
+

+ +

+ + + + + + +
+

+ +

Sign in by entering the code sent to email@address.com, or by clicking the magic link in the email.

+ + + + +
+
+
+
+ +
+
+
+

Auth Modal Contents Success

+ + +
+ +
+ +
+ + + + +

+ Success! Your account was created and you're signed in. +

+ +

In the future, you'll sign in with a code sent to your email. If you'd rather use a password, you can set one in My Account.

+
+ + + +
+
+
+ + +
+
+
+

Auth Modal Contents Success + PW

+ + +
+ +
+ +
+ + + + +

+ Success! Your account was created and you're signed in. +

+
+ +
+

+ + + This will be used to address you in emails, and when you leave comments. +

+ +

+ + +

+

+ + + If you don't set a password, you can always log in with a magic link or one-time code sent to your email. +

+
+ + + +
+
+
+ + +
+
+
+

Auth Modal Newsletter Sign Up

+ + +
+ +
+ +

Get the best of The News Paper directly to your email inbox.
+ Sending to: email@address.

+ + + + + + +
+
+
+ +
+
-
+
- +
+ +

+ +
-
+
@@ -1179,8 +1183,16 @@ function( $list ) {
- +
+ +
+ + +
+ +
@@ -1199,7 +1212,7 @@ function( $list ) {
- +

@@ -1213,6 +1226,8 @@ function( $list ) {

+
+ +
+ TODO finish up the footer. +
+
Date: Thu, 14 Dec 2023 17:43:04 -0800 Subject: [PATCH 022/243] feat: correct linting errors --- includes/class-newspack-ui.php | 5 +++++ includes/reader-activation/class-reader-activation.php | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 8d6d57ab9f..0c7128a47b 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -481,6 +481,11 @@ public static function return_demo_content() { return ob_get_clean(); } + /** + * Append the demo content when the ui-demo query string is used. + * @param string $content The page content. + * @return string Modified $content with demo appended. + */ public static function load_demo( $content ) { if ( isset( $_REQUEST['ui-demo'] ) ) { $content .= self::return_demo_content(); diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index 20e9487bde..96c6bed577 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -1070,7 +1070,6 @@ public static function render_auth_form( $is_inline = false ) {
-

-
+ -
+
@@ -1095,6 +1092,19 @@ public static function render_auth_form( $is_inline = false ) {

+
+ + + + + + +
+ +

+ +
+

@@ -1182,16 +1192,8 @@ function( $list ) {
- -
- -
- - +
- -
@@ -1211,7 +1212,7 @@ function( $list ) {
- +

@@ -1225,8 +1226,6 @@ function( $list ) {

-
- -
- TODO finish up the footer. -
-
Date: Fri, 15 Dec 2023 10:59:18 -0800 Subject: [PATCH 025/243] feat: add a check for admin for the demo components --- includes/class-newspack-ui.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index f620dc874a..76e388350f 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -488,7 +488,7 @@ public static function return_demo_content() { * @return string Modified $content with demo appended. */ public static function load_demo( $content ) { - if ( isset( $_REQUEST['ui-demo'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( isset( $_REQUEST['ui-demo'] ) && current_user_can('administrator') ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $content .= self::return_demo_content(); } return $content; From a661bbcd47fef6998fcccb3dcb6068dd2a59be2f Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 15 Dec 2023 13:10:06 -0800 Subject: [PATCH 026/243] fix: correct linting error --- includes/class-newspack-ui.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 76e388350f..a3904a6df0 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -488,7 +488,7 @@ public static function return_demo_content() { * @return string Modified $content with demo appended. */ public static function load_demo( $content ) { - if ( isset( $_REQUEST['ui-demo'] ) && current_user_can('administrator') ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( isset( $_REQUEST['ui-demo'] ) && current_user_can( 'administrator' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $content .= self::return_demo_content(); } return $content; From 5089ffe0df9b4e09d1bc381792e4ab9e2e234a4b Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 9 Jan 2024 16:03:31 -0800 Subject: [PATCH 027/243] fix: corrections for the modal styles --- assets/newspack-ui/scss/_modals.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index e7ab6cbb9c..414738ca0d 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -2,12 +2,13 @@ &__modal { background: var( --newspack-ui-color-body-bg ); border-radius: var( --newspack-ui-border-radius ); + max-height: 90vh; max-width: var( --newspack-ui-modal-width-medium ); overflow: hidden; // Modal header & footer &__header, - &__footer, { + &__footer { padding: var( --newspack-ui-spacer-4 ) var( --newspack-ui-spacer-5 ); } @@ -43,6 +44,7 @@ &__content { backface-visibility: visible; + overflow: auto; padding: var( --newspack-ui-spacer-5 ); } From 3bb8809a9c40527e54dcf1cb709812bef3a9f051 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 9 Jan 2024 16:04:22 -0800 Subject: [PATCH 028/243] fix: update the styles for now to use greyscale --- .../newspack-ui/scss/elements/forms/_labels.scss | 9 +++++---- assets/newspack-ui/scss/variables/_colors.scss | 14 -------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss index de18d6b9cc..68679b747b 100644 --- a/assets/newspack-ui/scss/elements/forms/_labels.scss +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -6,10 +6,11 @@ font-size: var( --newspack-ui-font-size-small ) !important; // !important to override Newspack Theme. font-weight: 600; line-height: var( --newspack-ui-line-height-small ); - margin: 0 0 var( --newspack-ui-spacer-1 ); + margin: 0 0 var( --newspack-ui-spacer-base ); // For labels containing radio, checkbox inputs: - &.newspack-ui__input-checkradio { // For Firefox; otherwise could use &:has( input[type='checkbox'] ),&:has( input[type='radio'] ) + &:has( input[type='checkbox'] ), + &:has( input[type='radio'] ) { align-items: center; display: flex; gap: var( --newspack-ui-spacer-2 ); @@ -25,8 +26,8 @@ // This selector isn't supported in Firefox yet. &:has( input:checked ) { - background: var( --newspack-ui-color-primary-000 ); - border-color: var( --newspack-ui-color-primary-500 ); + background: var( --newspack-ui-color-gray-100 ); + border-color: var( --newspack-ui-color-gray-900 ); } + .newspack-ui__input-list { diff --git a/assets/newspack-ui/scss/variables/_colors.scss b/assets/newspack-ui/scss/variables/_colors.scss index c18b13b7ef..49f336d161 100644 --- a/assets/newspack-ui/scss/variables/_colors.scss +++ b/assets/newspack-ui/scss/variables/_colors.scss @@ -1,18 +1,4 @@ :root { - // Newspack Blues - --newspack-ui-color-primary-000: #f5fdff; - --newspack-ui-color-primary-050: #d6f6ff; - --newspack-ui-color-primary-100: #b4e4ff; - --newspack-ui-color-primary-200: #93ccfd; - --newspack-ui-color-primary-300: #72affb; - --newspack-ui-color-primary-400: #528dfc; - --newspack-ui-color-primary-500: #36f; - --newspack-ui-color-primary-600: #2240d5; - --newspack-ui-color-primary-700: #1522af; - --newspack-ui-color-primary-800: #0b0b8d; - --newspack-ui-color-primary-900: #0d046e; - --newspack-ui-color-primary-950: #0e0052; - // Grays - notes from the Gutenberg styles. // TODO: Import from 'wordpress/base-styles/colors' ? --newspack-ui-color-black: #000; // Use only when you truly need pure black. For UI, use $gray-900. From d81a16709a64af9cae5fb89564ebdbc5acfd8c8b Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 9 Jan 2024 16:07:01 -0800 Subject: [PATCH 029/243] fix: separate woocommerce, misc styles --- assets/newspack-ui/scss/elements/_index.scss | 22 ++----------------- .../scss/elements/misc/_index.scss | 1 + .../scss/elements/misc/_word-divider.scss | 16 ++++++++++++++ .../scss/elements/woocommerce/_index.scss | 1 + .../scss/elements/woocommerce/_overrides.scss | 12 ++++++++++ assets/newspack-ui/style.scss | 11 ---------- 6 files changed, 32 insertions(+), 31 deletions(-) create mode 100644 assets/newspack-ui/scss/elements/misc/_index.scss create mode 100644 assets/newspack-ui/scss/elements/misc/_word-divider.scss create mode 100644 assets/newspack-ui/scss/elements/woocommerce/_index.scss create mode 100644 assets/newspack-ui/scss/elements/woocommerce/_overrides.scss diff --git a/assets/newspack-ui/scss/elements/_index.scss b/assets/newspack-ui/scss/elements/_index.scss index f974481509..8135ecc6d4 100644 --- a/assets/newspack-ui/scss/elements/_index.scss +++ b/assets/newspack-ui/scss/elements/_index.scss @@ -1,25 +1,7 @@ @use 'boxes'; @use 'forms'; @use 'icons'; +@use 'misc'; @use 'tables'; @use 'typography'; - -// TODO: Find a better home for this: -.newspack-ui { - &__word-divider { - align-items: center; - display: flex; - font-size: var( --newspack-ui-font-size-small ); - gap: var( --newspack-ui-spacer-2 ); - justify-content: space-evenly; - margin: var( --newspack-ui-spacer-5 ) 0; - - &::before, - &::after { - border-top: 1px solid var( --newspack-ui-color-border ); - content: ''; - display: block; - width: 100%; - } - } -} \ No newline at end of file +@use 'woocommerce'; diff --git a/assets/newspack-ui/scss/elements/misc/_index.scss b/assets/newspack-ui/scss/elements/misc/_index.scss new file mode 100644 index 0000000000..2271e94dd9 --- /dev/null +++ b/assets/newspack-ui/scss/elements/misc/_index.scss @@ -0,0 +1 @@ +@use 'word-divider'; \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/misc/_word-divider.scss b/assets/newspack-ui/scss/elements/misc/_word-divider.scss new file mode 100644 index 0000000000..02182d61a2 --- /dev/null +++ b/assets/newspack-ui/scss/elements/misc/_word-divider.scss @@ -0,0 +1,16 @@ +.newspack-ui__word-divider { + align-items: center; + display: flex; + font-size: var( --newspack-ui-font-size-small ); + gap: var( --newspack-ui-spacer-2 ); + justify-content: space-evenly; + margin: var( --newspack-ui-spacer-5 ) 0; + + &::before, + &::after { + border-top: 1px solid var( --newspack-ui-color-border ); + content: ''; + display: block; + width: 100%; + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/woocommerce/_index.scss b/assets/newspack-ui/scss/elements/woocommerce/_index.scss new file mode 100644 index 0000000000..a55ee981d6 --- /dev/null +++ b/assets/newspack-ui/scss/elements/woocommerce/_index.scss @@ -0,0 +1 @@ +@use 'overrides'; \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss new file mode 100644 index 0000000000..50e9ec6256 --- /dev/null +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -0,0 +1,12 @@ +// Some general overrides for WooCommerce styles. +.newspack-ui { + form p { + margin: 0 0 var( --newspack-ui-spacer-5 ); + } + + &__modal__small { + form p { + margin: 0 0 var( --newspack-ui-spacer-2 ); + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/style.scss b/assets/newspack-ui/style.scss index 68fce49d5a..b35f5b660b 100644 --- a/assets/newspack-ui/style.scss +++ b/assets/newspack-ui/style.scss @@ -21,15 +21,4 @@ a:hover { color: inherit !important; } - - // TODO: This specifically is a WooCommerce HTML structure; have been using it for other elements so far, but do we want to? - form p { - margin: 0 0 var( --newspack-ui-spacer-5 ); - } - - .newspack-ui__modal__small { - form p { - margin: 0 0 var( --newspack-ui-spacer-2 ); - } - } } From 616419d55954df6207d127cdd7764e4c85c9d5f5 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 9 Jan 2024 16:09:45 -0800 Subject: [PATCH 030/243] fix: cleaning up some post-rebase code --- .../reader-activation/class-reader-activation.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index 3566a15ebe..7157b2606e 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -1092,19 +1092,6 @@ public static function render_auth_form( $is_inline = false ) {

-
- - - - - - -
- -

- -
-

From 4f3dd42264a1692d0e80128fb3e4c661a39da971 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 9 Jan 2024 16:10:14 -0800 Subject: [PATCH 031/243] fix: remove unneeded CSS classes for Firefox fallback --- includes/class-newspack-ui.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index a3904a6df0..0c596a65cb 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -98,21 +98,21 @@ public static function return_demo_content() {

-

-

-


Checkbox/Radio Lists

-
-
+

Auth Modal Contents Success

- + -
+
-
+

Auth Modal Contents Success + PW

- - + + -
+
-
+

Auth Modal Newsletter Sign Up

- + -
+
From dad4664ea11649a96cbe9cf35fcef711735be9a6 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Mon, 22 Jan 2024 18:44:39 -0300 Subject: [PATCH 041/243] chore(auth): reorganize auth javascript --- assets/blocks/reader-registration/editor.scss | 2 +- assets/reader-activation-auth/google-oauth.js | 88 +++++++ .../index.js} | 237 +----------------- assets/reader-activation-auth/otp-input.js | 99 ++++++++ .../style.scss} | 0 assets/reader-activation-auth/utils.js | 56 +++++ webpack.config.js | 9 +- 7 files changed, 250 insertions(+), 241 deletions(-) create mode 100644 assets/reader-activation-auth/google-oauth.js rename assets/{reader-activation/auth.js => reader-activation-auth/index.js} (68%) create mode 100644 assets/reader-activation-auth/otp-input.js rename assets/{reader-activation/auth.scss => reader-activation-auth/style.scss} (100%) create mode 100644 assets/reader-activation-auth/utils.js diff --git a/assets/blocks/reader-registration/editor.scss b/assets/blocks/reader-registration/editor.scss index 00ba5480a3..7cef42e19c 100644 --- a/assets/blocks/reader-registration/editor.scss +++ b/assets/blocks/reader-registration/editor.scss @@ -1,5 +1,5 @@ @use './style'; -@use '../../reader-activation/auth'; +@use '../../reader-activation-auth/style' as auth; @use '~@wordpress/base-styles/colors' as wp-colors; .newspack-registration { diff --git a/assets/reader-activation-auth/google-oauth.js b/assets/reader-activation-auth/google-oauth.js new file mode 100644 index 0000000000..92f9c995a4 --- /dev/null +++ b/assets/reader-activation-auth/google-oauth.js @@ -0,0 +1,88 @@ +/* globals newspack_reader_auth_labels */ + +/** + * Internal dependencies. + */ +import { domReady, convertFormDataToObject } from './utils'; + +domReady( function () { + const loginsElements = document.querySelectorAll( '.newspack-reader__logins' ); + [ ...loginsElements ].forEach( element => { + element.classList.remove( 'newspack-reader__logins--disabled' ); + } ); + const googleLoginElements = document.querySelectorAll( '.newspack-reader__logins__google' ); + googleLoginElements.forEach( googleLoginElement => { + const googleLoginForm = googleLoginElement.closest( 'form' ); + const redirectInput = googleLoginForm.querySelector( 'input[name="redirect"]' ); + const checkLoginStatus = metadata => { + fetch( `/wp-json/newspack/v1/login/google/register?metadata=${ JSON.stringify( metadata ) }` ) + .then( res => { + res + .json() + .then( ( { message, data } ) => { + const redirect = redirectInput?.value || null; + if ( googleLoginForm?.endLoginFlow ) { + googleLoginForm.endLoginFlow( message, res.status, data, redirect ); + } + } ) + .catch( error => { + if ( googleLoginForm?.endLoginFlow ) { + googleLoginForm.endLoginFlow( error?.message, res.status ); + } + } ); + } ) + .catch( error => { + if ( googleLoginForm?.endLoginFlow ) { + googleLoginForm.endLoginFlow( error?.message ); + } + } ); + }; + + googleLoginElement.addEventListener( 'click', () => { + if ( googleLoginForm?.startLoginFlow ) { + googleLoginForm.startLoginFlow(); + } + + const metadata = googleLoginForm + ? convertFormDataToObject( new FormData( googleLoginForm ), [ 'lists[]' ] ) + : {}; + metadata.current_page_url = window.location.href; + const authWindow = window.open( + 'about:blank', + 'newspack_google_login', + 'width=500,height=600' + ); + fetch( '/wp-json/newspack/v1/login/google' ) + .then( res => res.json().then( data => Promise.resolve( { data, status: res.status } ) ) ) + .then( ( { data, status } ) => { + if ( status !== 200 ) { + if ( authWindow ) { + authWindow.close(); + } + if ( googleLoginForm?.endLoginFlow ) { + googleLoginForm.endLoginFlow( data.message, status ); + } + } else if ( authWindow ) { + authWindow.location = data; + const interval = setInterval( () => { + if ( authWindow.closed ) { + checkLoginStatus( metadata ); + clearInterval( interval ); + } + }, 500 ); + } else if ( googleLoginForm?.endLoginFlow ) { + googleLoginForm.endLoginFlow( newspack_reader_auth_labels.blocked_popup ); + } + } ) + .catch( error => { + console.log( error ); + if ( googleLoginForm?.endLoginFlow ) { + googleLoginForm.endLoginFlow( error?.message, 400 ); + } + if ( authWindow ) { + authWindow.close(); + } + } ); + } ); + } ); +} ); diff --git a/assets/reader-activation/auth.js b/assets/reader-activation-auth/index.js similarity index 68% rename from assets/reader-activation/auth.js rename to assets/reader-activation-auth/index.js index d75aafbe54..ad65d1ad7a 100644 --- a/assets/reader-activation/auth.js +++ b/assets/reader-activation-auth/index.js @@ -3,63 +3,12 @@ /** * Internal dependencies. */ -import './auth.scss'; +import { domReady, formatTime } from './utils'; -/** - * Specify a function to execute when the DOM is fully loaded. - * - * @see https://github.com/WordPress/gutenberg/blob/trunk/packages/dom-ready/ - * - * @param {Function} callback A function to execute after the DOM is ready. - * @return {void} - */ -function domReady( callback ) { - if ( typeof document === 'undefined' ) { - return; - } - if ( - document.readyState === 'complete' || // DOMContentLoaded + Images/Styles/etc loaded, so we call directly. - document.readyState === 'interactive' // DOMContentLoaded fires at this point, so we call directly. - ) { - return void callback(); - } - // DOMContentLoaded has not fired yet, delay callback until then. - document.addEventListener( 'DOMContentLoaded', callback ); -} +import './google-oauth'; +import './otp-input'; -/** - * Format time in MM:SS format. - * - * @param {number} time Time in seconds. - */ -function formatTime( time ) { - const minutes = Math.floor( time / 60 ); - const seconds = time % 60; - return `${ minutes }:${ seconds < 10 ? '0' : '' }${ seconds }`; -} - -/** - * Converts FormData into an object. - * - * @param {FormData} formData The form data to convert. - * @param {Array} includedFields Form fields to include. - * - * @return {Object} The converted form data. - */ -const convertFormDataToObject = ( formData, includedFields = [] ) => - Array.from( formData.entries() ).reduce( ( acc, [ key, val ] ) => { - if ( ! includedFields.includes( key ) ) { - return acc; - } - if ( key.indexOf( '[]' ) > -1 ) { - key = key.replace( '[]', '' ); - acc[ key ] = acc[ key ] || []; - acc[ key ].push( val ); - } else { - acc[ key ] = val; - } - return acc; - }, {} ); +import './style.scss'; const SIGN_IN_MODAL_HASHES = [ 'signin_modal', 'register_modal' ]; @@ -556,183 +505,5 @@ window.newspackRAS.push( function ( readerActivation ) { } ); } ); } ); - - /** - * OTP Input - */ - const otpInputs = document.querySelectorAll( 'input[name="otp_code"]' ); - otpInputs.forEach( originalInput => { - const length = parseInt( originalInput.getAttribute( 'maxlength' ) ); - if ( ! length ) { - return; - } - const inputContainer = originalInput.parentNode; - inputContainer.removeChild( originalInput ); - const values = []; - const otpCodeInput = document.createElement( 'input' ); - otpCodeInput.setAttribute( 'type', 'hidden' ); - otpCodeInput.setAttribute( 'name', 'otp_code' ); - inputContainer.appendChild( otpCodeInput ); - for ( let i = 0; i < length; i++ ) { - const digit = document.createElement( 'input' ); - digit.setAttribute( 'type', 'text' ); - digit.setAttribute( 'maxlength', '1' ); - digit.setAttribute( 'pattern', '[0-9]' ); - digit.setAttribute( 'autocomplete', 'off' ); - digit.setAttribute( 'inputmode', 'numeric' ); - digit.setAttribute( 'data-index', i ); - digit.addEventListener( 'keydown', ev => { - const prev = inputContainer.querySelector( `[data-index="${ i - 1 }"]` ); - const next = inputContainer.querySelector( `[data-index="${ i + 1 }"]` ); - switch ( ev.key ) { - case 'Backspace': - ev.preventDefault(); - ev.target.value = ''; - if ( prev ) { - prev.focus(); - } - values[ i ] = ''; - otpCodeInput.value = values.join( '' ); - break; - case 'ArrowLeft': - ev.preventDefault(); - if ( prev ) { - prev.focus(); - } - break; - case 'ArrowRight': - ev.preventDefault(); - if ( next ) { - next.focus(); - } - break; - default: - if ( ev.key.match( /^[0-9]$/ ) ) { - ev.preventDefault(); - ev.target.value = ev.key; - ev.target.dispatchEvent( - new Event( 'input', { - bubbles: true, - cancelable: true, - } ) - ); - if ( next ) { - next.focus(); - } - } - break; - } - } ); - digit.addEventListener( 'input', ev => { - if ( ev.target.value.match( /^[0-9]$/ ) ) { - values[ i ] = ev.target.value; - } else { - ev.target.value = ''; - } - otpCodeInput.value = values.join( '' ); - } ); - digit.addEventListener( 'paste', ev => { - ev.preventDefault(); - const paste = ( ev.clipboardData || window.clipboardData ).getData( 'text' ); - if ( paste.length !== length ) { - return; - } - for ( let j = 0; j < length; j++ ) { - if ( paste[ j ].match( /^[0-9]$/ ) ) { - const digitInput = inputContainer.querySelector( `[data-index="${ j }"]` ); - digitInput.value = paste[ j ]; - values[ j ] = paste[ j ]; - } - } - otpCodeInput.value = values.join( '' ); - } ); - inputContainer.appendChild( digit ); - } - } ); - - /** - * Third party auth. - */ - const loginsElements = document.querySelectorAll( '.newspack-reader__logins' ); - [ ...loginsElements ].forEach( element => { - element.classList.remove( 'newspack-reader__logins--disabled' ); - } ); - const googleLoginElements = document.querySelectorAll( '.newspack-reader__logins__google' ); - googleLoginElements.forEach( googleLoginElement => { - const googleLoginForm = googleLoginElement.closest( 'form' ); - const redirectInput = googleLoginForm.querySelector( 'input[name="redirect"]' ); - const checkLoginStatus = metadata => { - fetch( - `/wp-json/newspack/v1/login/google/register?metadata=${ JSON.stringify( metadata ) }` - ) - .then( res => { - res - .json() - .then( ( { message, data } ) => { - const redirect = redirectInput?.value || null; - if ( googleLoginForm?.endLoginFlow ) { - googleLoginForm.endLoginFlow( message, res.status, data, redirect ); - } - } ) - .catch( error => { - if ( googleLoginForm?.endLoginFlow ) { - googleLoginForm.endLoginFlow( error?.message, res.status ); - } - } ); - } ) - .catch( error => { - if ( googleLoginForm?.endLoginFlow ) { - googleLoginForm.endLoginFlow( error?.message ); - } - } ); - }; - - googleLoginElement.addEventListener( 'click', () => { - if ( googleLoginForm?.startLoginFlow ) { - googleLoginForm.startLoginFlow(); - } - - const metadata = googleLoginForm - ? convertFormDataToObject( new FormData( googleLoginForm ), [ 'lists[]' ] ) - : {}; - metadata.current_page_url = window.location.href; - const authWindow = window.open( - 'about:blank', - 'newspack_google_login', - 'width=500,height=600' - ); - fetch( '/wp-json/newspack/v1/login/google' ) - .then( res => res.json().then( data => Promise.resolve( { data, status: res.status } ) ) ) - .then( ( { data, status } ) => { - if ( status !== 200 ) { - if ( authWindow ) { - authWindow.close(); - } - if ( googleLoginForm?.endLoginFlow ) { - googleLoginForm.endLoginFlow( data.message, status ); - } - } else if ( authWindow ) { - authWindow.location = data; - const interval = setInterval( () => { - if ( authWindow.closed ) { - checkLoginStatus( metadata ); - clearInterval( interval ); - } - }, 500 ); - } else if ( googleLoginForm?.endLoginFlow ) { - googleLoginForm.endLoginFlow( newspack_reader_auth_labels.blocked_popup ); - } - } ) - .catch( error => { - console.log( error ); - if ( googleLoginForm?.endLoginFlow ) { - googleLoginForm.endLoginFlow( error?.message, 400 ); - } - if ( authWindow ) { - authWindow.close(); - } - } ); - } ); - } ); } ); } ); diff --git a/assets/reader-activation-auth/otp-input.js b/assets/reader-activation-auth/otp-input.js new file mode 100644 index 0000000000..fe6fecbf3c --- /dev/null +++ b/assets/reader-activation-auth/otp-input.js @@ -0,0 +1,99 @@ +/** + * Internal dependencies. + */ +import { domReady } from './utils'; + +domReady( function () { + /** + * OTP Input + */ + const otpInputs = document.querySelectorAll( 'input[name="otp_code"]' ); + otpInputs.forEach( originalInput => { + const length = parseInt( originalInput.getAttribute( 'maxlength' ) ); + if ( ! length ) { + return; + } + const inputContainer = originalInput.parentNode; + inputContainer.removeChild( originalInput ); + const values = []; + const otpCodeInput = document.createElement( 'input' ); + otpCodeInput.setAttribute( 'type', 'hidden' ); + otpCodeInput.setAttribute( 'name', 'otp_code' ); + inputContainer.appendChild( otpCodeInput ); + for ( let i = 0; i < length; i++ ) { + const digit = document.createElement( 'input' ); + digit.setAttribute( 'type', 'text' ); + digit.setAttribute( 'maxlength', '1' ); + digit.setAttribute( 'pattern', '[0-9]' ); + digit.setAttribute( 'autocomplete', 'off' ); + digit.setAttribute( 'inputmode', 'numeric' ); + digit.setAttribute( 'data-index', i ); + digit.addEventListener( 'keydown', ev => { + const prev = inputContainer.querySelector( `[data-index="${ i - 1 }"]` ); + const next = inputContainer.querySelector( `[data-index="${ i + 1 }"]` ); + switch ( ev.key ) { + case 'Backspace': + ev.preventDefault(); + ev.target.value = ''; + if ( prev ) { + prev.focus(); + } + values[ i ] = ''; + otpCodeInput.value = values.join( '' ); + break; + case 'ArrowLeft': + ev.preventDefault(); + if ( prev ) { + prev.focus(); + } + break; + case 'ArrowRight': + ev.preventDefault(); + if ( next ) { + next.focus(); + } + break; + default: + if ( ev.key.match( /^[0-9]$/ ) ) { + ev.preventDefault(); + ev.target.value = ev.key; + ev.target.dispatchEvent( + new Event( 'input', { + bubbles: true, + cancelable: true, + } ) + ); + if ( next ) { + next.focus(); + } + } + break; + } + } ); + digit.addEventListener( 'input', ev => { + if ( ev.target.value.match( /^[0-9]$/ ) ) { + values[ i ] = ev.target.value; + } else { + ev.target.value = ''; + } + otpCodeInput.value = values.join( '' ); + } ); + digit.addEventListener( 'paste', ev => { + ev.preventDefault(); + const paste = ( ev.clipboardData || window.clipboardData ).getData( 'text' ); + if ( paste.length !== length ) { + return; + } + for ( let j = 0; j < length; j++ ) { + if ( paste[ j ].match( /^[0-9]$/ ) ) { + const digitInput = inputContainer.querySelector( `[data-index="${ j }"]` ); + digitInput.value = paste[ j ]; + values[ j ] = paste[ j ]; + } + } + otpCodeInput.value = values.join( '' ); + } ); + inputContainer.appendChild( digit ); + } + } ); +} ); diff --git a/assets/reader-activation/auth.scss b/assets/reader-activation-auth/style.scss similarity index 100% rename from assets/reader-activation/auth.scss rename to assets/reader-activation-auth/style.scss diff --git a/assets/reader-activation-auth/utils.js b/assets/reader-activation-auth/utils.js new file mode 100644 index 0000000000..22b29bf76f --- /dev/null +++ b/assets/reader-activation-auth/utils.js @@ -0,0 +1,56 @@ +/** + * Specify a function to execute when the DOM is fully loaded. + * + * @see https://github.com/WordPress/gutenberg/blob/trunk/packages/dom-ready/ + * + * @param {Function} callback A function to execute after the DOM is ready. + * @return {void} + */ +export function domReady( callback ) { + if ( typeof document === 'undefined' ) { + return; + } + if ( + document.readyState === 'complete' || // DOMContentLoaded + Images/Styles/etc loaded, so we call directly. + document.readyState === 'interactive' // DOMContentLoaded fires at this point, so we call directly. + ) { + return void callback(); + } + // DOMContentLoaded has not fired yet, delay callback until then. + document.addEventListener( 'DOMContentLoaded', callback ); +} + +/** + * Format time in MM:SS format. + * + * @param {number} time Time in seconds. + */ +export function formatTime( time ) { + const minutes = Math.floor( time / 60 ); + const seconds = time % 60; + return `${ minutes }:${ seconds < 10 ? '0' : '' }${ seconds }`; +} + +/** + * Converts FormData into an object. + * + * @param {FormData} formData The form data to convert. + * @param {Array} includedFields Form fields to include. + * + * @return {Object} The converted form data. + */ +export function convertFormDataToObject( formData, includedFields = [] ) { + return Array.from( formData.entries() ).reduce( ( acc, [ key, val ] ) => { + if ( ! includedFields.includes( key ) ) { + return acc; + } + if ( key.indexOf( '[]' ) > -1 ) { + key = key.replace( '[]', '' ); + acc[ key ] = acc[ key ] || []; + acc[ key ].push( val ); + } else { + acc[ key ] = val; + } + return acc; + }, {} ); +} diff --git a/webpack.config.js b/webpack.config.js index 12db8157a6..252bf6c524 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -59,7 +59,7 @@ const webpackConfig = getBaseWebpackConfig( ...wizardsScriptFiles, blocks: path.join( __dirname, 'assets', 'blocks', 'index.js' ), 'reader-activation': path.join( __dirname, 'assets', 'reader-activation', 'index.js' ), - 'reader-auth': path.join( __dirname, 'assets', 'reader-activation', 'auth.js' ), + 'reader-auth': path.join( __dirname, 'assets', 'reader-activation-auth', 'index.js' ), 'reader-registration-block': path.join( __dirname, 'assets', @@ -83,12 +83,7 @@ const webpackConfig = getBaseWebpackConfig( 'memberships-gate', 'block-patterns.js' ), - 'newspack-ui': path.join( - __dirname, - 'assets', - 'newspack-ui', - 'index.js' - ), + 'newspack-ui': path.join( __dirname, 'assets', 'newspack-ui', 'index.js' ), }, } ); From b66c716211ad09f4c387430bd63a995a763c4888 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 23 Jan 2024 08:58:29 -0800 Subject: [PATCH 042/243] feat: add primary theme color for modal buttons --- assets/newspack-ui/scss/_modals.scss | 5 ++++ .../scss/elements/forms/_buttons.scss | 3 ++ .../newspack-ui/scss/variables/_colors.scss | 5 ++++ includes/class-newspack-ui.php | 28 +++++++++++++++++-- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 38f20fa803..dd8b50fce3 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -39,6 +39,11 @@ } } &__modal { + // CSS Variables - update button background, with fallbacks to the Newspack UI defaults + --newspack-ui-color-button-bg: var( --newspack-ui-color-primary, var( --newspack-ui-color-gray-900 ) ); + --newspack-ui-color-button-text: var( --newspack-ui-color-against-primary, var( --newspack-ui-color-white ) ); + + // Modal styles background: var( --newspack-ui-color-body-bg ); border-radius: var( --newspack-ui-border-radius ); display: flex; diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index bf62884063..cec8432ee9 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -41,6 +41,7 @@ &:hover { background: var( --newspack-ui-color-button-bg-hover ); + color: var( --newspack-ui-color-button-text-hover ); } } @@ -53,6 +54,7 @@ &:hover { background: var( --newspack-ui-color-gray-100 ); + color: var( --newspack-ui-color-text-high-contrast ); } } @@ -62,6 +64,7 @@ &:hover { background: var( --newspack-ui-color-gray-100 ); + color: var( --newspack-ui-color-text-high-contrast ); } } } diff --git a/assets/newspack-ui/scss/variables/_colors.scss b/assets/newspack-ui/scss/variables/_colors.scss index 49f336d161..62d081fbb1 100644 --- a/assets/newspack-ui/scss/variables/_colors.scss +++ b/assets/newspack-ui/scss/variables/_colors.scss @@ -20,6 +20,10 @@ --newspack-ui-color-alert-green-bg: #edfaef; --newpsack-ui-color-alert-red-bg: #fcf0f1; + // Theme variables - from the classic theme; overridden in class-newspack-ui.php for block theme. + --newspack-ui-color-primary: var(--newspack-theme-color-primary); + --newspack-ui-color-against-primary: var(--newspack-theme-color-against-primary); + // Specific assignments - general: --newspack-ui-color-text-high-contrast: var( --newspack-ui-color-gray-900 ); --newspack-ui-color-text-med-contrast: var( --newspack-ui-color-gray-700 ); @@ -30,5 +34,6 @@ --newspack-ui-color-button-bg: var( --newspack-ui-color-gray-900 ); --newspack-ui-color-button-bg-hover: var( --newspack-ui-color-gray-800 ); // TODO: Replace w/correct value. --newspack-ui-color-button-text: var( --newspack-ui-color-white ); + --newspack-ui-color-button-text-hover: var( --newspack-ui-color-white ); --newspack-ui-color-radio-bg: var( --newspack-ui-color-gray-900 ); } \ No newline at end of file diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index c7b4fcdd3f..dd9f3c7974 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -19,10 +19,14 @@ class Newspack_UI { public static function init() { \add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_styles' ] ); \add_filter( 'the_content', [ __CLASS__, 'load_demo' ] ); + // Only run if the site is using a block theme. + if ( wp_theme_has_theme_json() ) { + \add_action( 'wp_enqueue_scripts', [ __CLASS__, 'colors_css_wrap' ] ); + } } /** - * Enqueue script and styles for Handoff Banner. + * Enqueue styles for the Newspack UI. */ public static function enqueue_styles() { \wp_enqueue_style( @@ -33,6 +37,24 @@ public static function enqueue_styles() { ); } + /** + * Adds inline styles CSS for the element/button colors from the theme.json. + * See: https://developer.wordpress.org/reference/functions/wp_get_global_styles/ + */ + public static function colors_css_wrap() { + $global_styles = wp_get_global_styles(); + + $custom_css = 'body {'; + if ( isset( $global_styles['elements']['button']['color']['background'] ) ) { + $custom_css .= '--newspack-ui-color-primary: ' . $global_styles['elements']['button']['color']['background'] . ';'; + } + if ( isset( $global_styles['elements']['button']['color']['text'] ) ) { + $custom_css .= '--newspack-ui-color-against-primary: ' . $global_styles['elements']['button']['color']['text'] . ';'; + } + $custom_css .= '}'; + wp_add_inline_style( 'newspack-ui', $custom_css ); + } + /** * Make a page to demo these components */ @@ -202,7 +224,7 @@ public static function return_demo_content() {

Buttons

newspack-ui__button--primary, --secondary, and --tertiary classes for colours/borders, and newspack-ui__button--wide for being 100% wide

-
+



@@ -476,7 +498,7 @@ public static function return_demo_content() {
- +
From e28ef304215f88d970f1010330727727ab2aeb21 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 23 Jan 2024 09:41:36 -0800 Subject: [PATCH 043/243] fix: update classes in modal demo --- includes/class-newspack-ui.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index dd9f3c7974..08a99f7d48 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -515,7 +515,7 @@ public static function return_demo_content() {
-
From d2a61cf99d642c06727dd0b1aad20b1a4d8a8a76 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 23 Jan 2024 10:42:19 -0800 Subject: [PATCH 044/243] fix: correct SCSS formatting --- assets/newspack-ui/scss/variables/_colors.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/newspack-ui/scss/variables/_colors.scss b/assets/newspack-ui/scss/variables/_colors.scss index 62d081fbb1..ee12e1285b 100644 --- a/assets/newspack-ui/scss/variables/_colors.scss +++ b/assets/newspack-ui/scss/variables/_colors.scss @@ -21,8 +21,8 @@ --newpsack-ui-color-alert-red-bg: #fcf0f1; // Theme variables - from the classic theme; overridden in class-newspack-ui.php for block theme. - --newspack-ui-color-primary: var(--newspack-theme-color-primary); - --newspack-ui-color-against-primary: var(--newspack-theme-color-against-primary); + --newspack-ui-color-primary: var( --newspack-theme-color-primary ); + --newspack-ui-color-against-primary: var( --newspack-theme-color-against-primary ); // Specific assignments - general: --newspack-ui-color-text-high-contrast: var( --newspack-ui-color-gray-900 ); From ff256ee26865256d6817d7885fc7456e7f22d347 Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Mon, 29 Jan 2024 12:59:00 -0300 Subject: [PATCH 045/243] feat(newspack-ui): use in authorisation flows (#2860) - feat: decouple auth form from modal - remove AMP support vestiges - fix: styling issues --------- Co-authored-by: Adam Boro --- assets/blocks/reader-registration/index.php | 6 +- assets/blocks/reader-registration/style.scss | 43 +- assets/newspack-ui/scss/_modals.scss | 7 +- assets/newspack-ui/scss/elements/_boxes.scss | 6 +- assets/newspack-ui/scss/elements/_icons.scss | 4 +- .../scss/elements/forms/_buttons.scss | 2 +- .../scss/elements/forms/_index.scss | 22 +- assets/newspack-ui/scss/variables/_fonts.scss | 4 +- assets/newspack-ui/style.scss | 6 +- assets/reader-activation-auth/auth-form.js | 367 ++++++++++++ assets/reader-activation-auth/auth-modal.js | 135 +++++ assets/reader-activation-auth/google-oauth.js | 6 +- assets/reader-activation-auth/index.js | 548 +++--------------- assets/reader-activation-auth/style.scss | 374 +----------- assets/reader-activation/index.js | 45 +- includes/class-magic-link.php | 6 +- includes/class-newspack-ui.php | 8 +- includes/class-recaptcha.php | 12 + .../class-reader-activation.php | 346 +++++------ .../reader-activation/login-form.php | 9 +- 20 files changed, 880 insertions(+), 1076 deletions(-) create mode 100644 assets/reader-activation-auth/auth-form.js create mode 100644 assets/reader-activation-auth/auth-modal.js diff --git a/assets/blocks/reader-registration/index.php b/assets/blocks/reader-registration/index.php index a692cca206..39f4323dbe 100644 --- a/assets/blocks/reader-registration/index.php +++ b/assets/blocks/reader-registration/index.php @@ -260,6 +260,7 @@ function render_block( $attrs, $content ) { ?>
+
-

@@ -319,10 +319,6 @@ function render_block( $attrs, $content ) {
- -
*:first-child { - margin-top: 0 !important; - } - - > *:last-child { - margin-bottom: 0 !important; - } - } - } - - &--hidden { - display: none; - } - + &--hidden, + div:empty { display: none; } diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index dd8b50fce3..76d1b7d9f2 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -90,6 +90,8 @@ } &__content { + --newspack-ui-font-size-base: var( --newspack-ui-font-size-small ); + backface-visibility: visible; padding: var( --newspack-ui-spacer-5 ); } @@ -97,8 +99,11 @@ &__footer { background: var( --newspack-ui-color-gray-100 ); color: var( --newspack-ui-color-text-med-contrast ); - font-size: var( --newspack-ui-font-size-small ); + font-size: var( --newspack-ui-font-size-extra-small ); line-height: var( --newspack-ui-line-height-small ); + a { + text-decoration: underline; + } } // Narrow modal diff --git a/assets/newspack-ui/scss/elements/_boxes.scss b/assets/newspack-ui/scss/elements/_boxes.scss index 93499a2709..3e7ae09e14 100644 --- a/assets/newspack-ui/scss/elements/_boxes.scss +++ b/assets/newspack-ui/scss/elements/_boxes.scss @@ -11,11 +11,11 @@ background: var( --newspack-ui-color-alert-green-bg ); } - &__error { + &--error { background: var( --newspack-ui-color-alert-red-bg ); } - &__warning { + &--warning { // TODO } @@ -25,7 +25,7 @@ } // Text alignments - &__text-center { + &--text-center { text-align: center; } diff --git a/assets/newspack-ui/scss/elements/_icons.scss b/assets/newspack-ui/scss/elements/_icons.scss index b4a197a7ac..24ea5e1b63 100644 --- a/assets/newspack-ui/scss/elements/_icons.scss +++ b/assets/newspack-ui/scss/elements/_icons.scss @@ -14,12 +14,12 @@ color: var( --newspack-ui-color-body-bg ); } - &__error { + &--error { background: var( --newspack-ui-color-alert-red ); color: var( --newspack-ui-color-body-bg ); } - &__warning { + &--warning { background: var( --newspack-ui-color-alert-yellow ); color: var( --newspack-ui-color-body-bg ); } diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index cec8432ee9..ef1850f925 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -17,7 +17,7 @@ transition: background-color 150ms ease-in-out; &:hover { - // TODO + color: inherit; } &:focus { diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index 9985ed0b85..a9ca959326 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -11,8 +11,12 @@ } } + & &__last-child { + margin-bottom: 0; + } + select { - font-family: var( --newspack-ui-font-family); + font-family: var( --newspack-ui-font-family ); line-height: var( --newspack-ui-line-height-large ); } @@ -20,6 +24,9 @@ & &__code-input { display: flex; gap: var( --newspack-ui-spacer-base ); + input { + text-align: center; + } } // Container for input description. @@ -29,4 +36,15 @@ line-height: var( --newspack-ui-line-height-small ); margin: var( --newspack-ui-spacer-base ) 0 var( --newspack-ui-spacer-5 ); } -} \ No newline at end of file + + // Form response inline error text. + &__inline-error { + color: var( --newspack-ui-color-alert-red ); + font-size: var( --newspack-ui-font-size-small ); + line-height: var( --newspack-ui-line-height-small ); + margin: var( --newspack-ui-spacer-base ) 0 var( --newspack-ui-spacer-5 ); + a { + text-decoration: underline; + } + } +} diff --git a/assets/newspack-ui/scss/variables/_fonts.scss b/assets/newspack-ui/scss/variables/_fonts.scss index 3ad47f8291..da6e123c16 100644 --- a/assets/newspack-ui/scss/variables/_fonts.scss +++ b/assets/newspack-ui/scss/variables/_fonts.scss @@ -8,10 +8,12 @@ --newspack-ui-font-size-large: 20px; --newspack-ui-font-size-medium: 16px; // modal baseline --newspack-ui-font-size-small: 14px; // modal small + --newspack-ui-font-size-extra-small: 12px; // modal extra small + --newspack-ui-font-size-base: var( --newspack-ui-font-size-medium ); --newspack-ui-font-weight-strong: 600; // Line heights - TODO: sort this out: --newspack-ui-line-height-large: 1.7143; // inputs, buttons --newspack-ui-line-height-medium: 1.5; // 16px font size --newspack-ui-line-height-small: 1.4286; // 14px font sizes -} \ No newline at end of file +} diff --git a/assets/newspack-ui/style.scss b/assets/newspack-ui/style.scss index b35f5b660b..b8e1ac5b26 100644 --- a/assets/newspack-ui/style.scss +++ b/assets/newspack-ui/style.scss @@ -4,7 +4,7 @@ .newspack-ui { font-family: var( --newspack-ui-font-family ); - font-size: var( --newspack-ui-font-size-medium ) !important; + font-size: var( --newspack-ui-font-size-base ); // Need better spot for this &__color-text-gray { @@ -19,6 +19,8 @@ a, a:hover { - color: inherit !important; + &:not( .newspack-ui__button ) { + color: inherit; + } } } diff --git a/assets/reader-activation-auth/auth-form.js b/assets/reader-activation-auth/auth-form.js new file mode 100644 index 0000000000..f0b9db6565 --- /dev/null +++ b/assets/reader-activation-auth/auth-form.js @@ -0,0 +1,367 @@ +/* globals newspack_reader_auth_labels */ + +/** + * Internal dependencies. + */ +import { domReady, formatTime } from './utils'; + +import './google-oauth'; +import './otp-input'; + +import './style.scss'; + +const FORM_ALLOWED_ACTIONS = [ 'register', 'signin', 'pwd', 'otp', 'success' ]; + +window.newspackRAS = window.newspackRAS || []; + +window.newspackRAS.push( function ( readerActivation ) { + domReady( function () { + const containers = [ ...document.querySelectorAll( '.newspack-reader-auth' ) ]; + if ( ! containers?.length ) { + return; + } + + containers.forEach( container => { + const form = container.querySelector( 'form' ); + if ( ! form ) { + return; + } + + const actionInput = form.querySelector( 'input[name="action"]' ); + const emailInput = form.querySelector( 'input[name="npe"]' ); + const otpCodeInput = form.querySelector( 'input[name="otp_code"]' ); + const passwordInput = form.querySelector( 'input[name="password"]' ); + const submitButtons = form.querySelectorAll( '[type="submit"]' ); + const backButtons = container.querySelectorAll( '[data-back]' ); + const sendCodeButtons = container.querySelectorAll( '[data-send-code]' ); + const messageContentElement = container.querySelector( '.response' ); + + /** + * Handle auth form action selection. + */ + let formAction; + container.setFormAction = ( action, shouldFocus = false ) => { + if ( ! FORM_ALLOWED_ACTIONS.includes( action ) ) { + action = 'signin'; + } + if ( 'otp' === action ) { + if ( ! readerActivation.getOTPHash() ) { + return; + } + const emailAddressElements = container.querySelectorAll( '.email-address' ); + emailAddressElements.forEach( element => { + element.textContent = readerActivation.getReader()?.email || ''; + } ); + // Focus on the first input. + const firstInput = container.querySelector( '.otp-field input[type="text"]' ); + if ( firstInput ) { + firstInput.focus(); + } + } + formAction = action; + actionInput.value = action; + container.removeAttribute( 'data-form-status' ); + messageContentElement.style.display = 'none'; + messageContentElement.innerHTML = ''; + container.querySelectorAll( '[data-action]' ).forEach( item => { + if ( 'none' !== item.style.display ) { + item.prevDisplay = item.style.display; + } + item.style.display = 'none'; + } ); + container.querySelectorAll( '[data-action~="' + action + '"]' ).forEach( item => { + item.style.display = item.prevDisplay; + } ); + if ( shouldFocus ) { + if ( action === 'pwd' && emailInput.value ) { + passwordInput.focus(); + } else if ( action === 'otp' ) { + otpCodeInput.focus(); + } else { + emailInput.focus(); + } + } + if ( container.formActionCallback ) { + container.formActionCallback( action ); + } + }; + container.setFormAction( 'signin' ); + + /** + * Handle reader changes. + */ + const handleReaderChanges = () => { + const reader = readerActivation.getReader(); + if ( emailInput ) { + emailInput.value = reader?.email || ''; + } + setTimeout( function () { + if ( reader?.authenticated && formAction !== 'success' ) { + form.endLoginFlow( null, 200 ); + } + }, 1000 ); + }; + readerActivation.on( 'reader', handleReaderChanges ); + handleReaderChanges(); + + backButtons.forEach( backButton => { + backButton.addEventListener( 'click', function ( ev ) { + ev.preventDefault(); + container.setFormAction( 'signin', true ); + } ); + } ); + + /** + * Handle OTP Timer. + */ + const handleOTPTimer = () => { + if ( ! sendCodeButtons.length ) { + return; + } + sendCodeButtons.forEach( button => { + button.originalButtonText = button.textContent; + if ( button.otpTimerInterval ) { + clearInterval( button.otpTimerInterval ); + } + const updateButton = () => { + const remaining = readerActivation.getOTPTimeRemaining(); + if ( remaining ) { + button.textContent = `${ button.originalButtonText } (${ formatTime( remaining ) })`; + button.disabled = true; + } else { + button.textContent = button.originalButtonText; + button.disabled = false; + clearInterval( button.otpTimerInterval ); + } + }; + const remaining = readerActivation.getOTPTimeRemaining(); + if ( remaining ) { + button.otpTimerInterval = setInterval( updateButton, 1000 ); + updateButton(); + } + } ); + }; + + if ( sendCodeButtons.length ) { + handleOTPTimer(); + sendCodeButtons.forEach( button => { + button.addEventListener( 'click', function ( ev ) { + messageContentElement.innerHTML = ''; + ev.preventDefault(); + form.startLoginFlow(); + const body = new FormData(); + body.set( 'reader-activation-auth-form', 1 ); + body.set( 'npe', emailInput.value ); + body.set( 'action', 'link' ); + readerActivation + .getCaptchaToken() + .then( captchaToken => { + if ( ! captchaToken ) { + return; + } + body.set( 'captcha_token', captchaToken ); + } ) + .catch( e => { + console.log( { e } ); + } ) + .finally( () => { + fetch( form.getAttribute( 'action' ) || window.location.pathname, { + method: 'POST', + headers: { + Accept: 'application/json', + }, + body, + } ) + .then( () => { + messageContentElement.style.display = 'block'; + messageContentElement.innerHTML = newspack_reader_auth_labels.code_resent; + container.setFormAction( 'otp' ); + readerActivation.setOTPTimer(); + } ) + .catch( e => { + console.log( e ); + } ) + .finally( () => { + handleOTPTimer(); + form.style.opacity = 1; + submitButtons.forEach( submitButton => { + submitButton.disabled = false; + } ); + } ); + } ); + } ); + } ); + } + + container.querySelectorAll( '[data-set-action]' ).forEach( item => { + item.addEventListener( 'click', function ( ev ) { + ev.preventDefault(); + container.setFormAction( ev.target.getAttribute( 'data-set-action' ), true ); + } ); + } ); + + form.startLoginFlow = () => { + container.removeAttribute( 'data-form-status' ); + submitButtons.forEach( button => { + button.disabled = true; + } ); + messageContentElement.innerHTML = ''; + form.style.opacity = 0.5; + }; + + form.endLoginFlow = ( message = null, status = 500, data = null ) => { + container.setAttribute( 'data-form-status', status ); + form.style.opacity = 1; + submitButtons.forEach( button => { + button.disabled = false; + } ); + if ( message ) { + const messageNode = document.createElement( 'p' ); + messageNode.innerHTML = message; + messageContentElement.style.display = 'block'; + messageContentElement.appendChild( messageNode ); + } + if ( status === 200 ) { + if ( data ) { + readerActivation.setReaderEmail( data.email ); + readerActivation.setAuthenticated( !! data.authenticated ); + } + + /** Resolve the modal immediately or display the "success" state. */ + if ( container.config?.skipSuccess ) { + if ( container.authCallback ) { + container.authCallback( message, data ); + } + } else { + let labels = newspack_reader_auth_labels.signin; + if ( data.registered ) { + labels = newspack_reader_auth_labels.register; + } + container.setFormAction( 'success' ); + container.querySelector( '.success-title' ).innerHTML = labels.success_title || ''; + container.querySelector( '.success-description' ).innerHTML = + labels.success_description || ''; + const callbackButton = container.querySelector( '.auth-callback' ); + if ( callbackButton ) { + callbackButton.addEventListener( 'click', ev => { + ev.preventDefault(); + if ( container.authCallback ) { + container.authCallback( message, data ); + } + } ); + } + + const setPasswordButton = container.querySelector( '.set-password' ); + if ( setPasswordButton ) { + const originalDisplay = setPasswordButton.style.display; + if ( data?.password_url ) { + setPasswordButton.style.display = originalDisplay; + setPasswordButton.setAttribute( 'href', data.password_url ); + } else { + setPasswordButton.style.display = 'none'; + setPasswordButton.setAttribute( 'href', '#' ); + } + } + } + } + }; + + /** + * Handle auth form submission. + */ + form.addEventListener( 'submit', ev => { + ev.preventDefault(); + form.startLoginFlow(); + + const action = form.action?.value; + + if ( ! form.npe?.value ) { + return form.endLoginFlow( newspack_reader_auth_labels.invalid_email, 400 ); + } + + if ( 'pwd' === action && ! form.password?.value ) { + return form.endLoginFlow( newspack_reader_auth_labels.invalid_password, 400 ); + } + + readerActivation + .getCaptchaToken() + .then( captchaToken => { + if ( ! captchaToken ) { + return; + } + let tokenField = form.captcha_token; + if ( ! tokenField ) { + tokenField = document.createElement( 'input' ); + tokenField.setAttribute( 'type', 'hidden' ); + tokenField.setAttribute( 'name', 'captcha_token' ); + tokenField.setAttribute( 'autocomplete', 'off' ); + form.appendChild( tokenField ); + } + tokenField.value = captchaToken; + } ) + .catch( e => { + form.endLoginFlow( e, 400 ); + } ) + .finally( () => { + const body = new FormData( ev.target ); + if ( ! body.has( 'npe' ) || ! body.get( 'npe' ) ) { + return form.endLoginFlow( newspack_reader_auth_labels.invalid_email, 400 ); + } + if ( 'otp' === action ) { + readerActivation + .authenticateOTP( body.get( 'otp_code' ) ) + .then( data => { + form.endLoginFlow( data.message, 200, data ); + } ) + .catch( data => { + if ( data.expired ) { + container.setFormAction( 'signin' ); + } + form.endLoginFlow( data.message, 400 ); + } ); + } else { + fetch( form.getAttribute( 'action' ) || window.location.pathname, { + method: 'POST', + headers: { + Accept: 'application/json', + }, + body, + } ) + .then( res => { + container.setAttribute( 'data-form-status', res.status ); + res + .json() + .then( ( { message, data } ) => { + const status = res.status; + if ( status === 200 ) { + readerActivation.setReaderEmail( body.get( 'npe' ) ); + } + if ( data.action ) { + container.setFormAction( data.action, true ); + if ( data.action === 'otp' ) { + readerActivation.setOTPTimer(); + handleOTPTimer(); + } + } else { + form.endLoginFlow( message, status, data ); + } + } ) + .catch( () => { + form.endLoginFlow(); + } ) + .finally( () => { + form.style.opacity = 1; + submitButtons.forEach( button => { + button.disabled = false; + } ); + } ); + } ) + .catch( () => { + form.endLoginFlow(); + } ); + } + } ); + } ); + } ); + } ); +} ); diff --git a/assets/reader-activation-auth/auth-modal.js b/assets/reader-activation-auth/auth-modal.js new file mode 100644 index 0000000000..760e7b5e3a --- /dev/null +++ b/assets/reader-activation-auth/auth-modal.js @@ -0,0 +1,135 @@ +/* globals newspack_reader_auth_labels */ +export const SIGN_IN_MODAL_HASHES = [ 'signin_modal', 'register_modal' ]; + +/** + * Get the authentication modal container. + * + * @return {HTMLElement} The modal container. + */ +export function getModalContainer() { + return document.querySelector( '.newspack-reader-auth-modal .newspack-reader-auth' ); +} + +/** + * Open the authentication modal. + * + * @param {Object} config Configuration object. + * + * @return {void} + */ +export function openAuthModal( config = {} ) { + const reader = window.newspackReaderActivation.getReader(); + if ( reader?.authenticated ) { + if ( config.callback ) { + config.callback(); + } + return; + } + + const container = getModalContainer(); + if ( ! container ) { + if ( config.callback ) { + config.callback(); + } + return; + } + + const modal = container.closest( '.newspack-reader-auth-modal' ); + if ( ! modal ) { + if ( config.callback ) { + config.callback(); + } + return; + } + + const close = () => { + container.config = {}; + modal.setAttribute( 'data-state', 'closed' ); + document.body.classList.remove( 'newspack-signin' ); + if ( modal.overlayId && window.newspackReaderActivation?.overlays ) { + window.newspackReaderActivation.overlays.remove( modal.overlayId ); + } + const openerContent = container.querySelector( '.opener-content' ); + if ( openerContent ) { + openerContent.remove(); + } + }; + + const closeButtons = modal.querySelectorAll( 'button[data-close], .newspack-ui__modal__close' ); + if ( closeButtons?.length ) { + closeButtons.forEach( closeButton => { + closeButton.addEventListener( 'click', function ( ev ) { + ev.preventDefault(); + close(); + } ); + } ); + } + + config.labels = { + ...newspack_reader_auth_labels, + ...config?.labels, + }; + + /** Attach config to the container. */ + container.config = config; + + container.authCallback = ( message, data ) => { + close(); + if ( config.callback ) { + config.callback( message, data ); + } + }; + + container.formActionCallback = action => { + const titleEl = modal.querySelector( 'h2' ); + titleEl.textContent = + 'register' === action ? config.labels.register.title : config.labels.signin.title; + + modal.querySelectorAll( '[data-action]' ).forEach( item => { + if ( 'none' !== item.style.display ) { + item.prevDisplay = item.style.display; + } + item.style.display = 'none'; + } ); + modal.querySelectorAll( '[data-action~="' + action + '"]' ).forEach( item => { + item.style.display = item.prevDisplay; + } ); + }; + + if ( config.content ) { + const openerContent = document.createElement( 'div' ); + openerContent.classList.add( 'opener-content' ); + openerContent.innerHTML = config.content; + const form = container.querySelector( 'form' ); + form.insertBefore( openerContent, form.firstChild ); + } + + const emailInput = container.querySelector( 'input[name="npe"]' ); + if ( emailInput ) { + emailInput.value = reader?.email || ''; + } + + let initialFormAction = 'signin'; + if ( window.newspackReaderActivation?.hasAuthLink() ) { + initialFormAction = 'otp'; + } + const currentHash = window.location.hash.replace( '#', '' ); + if ( SIGN_IN_MODAL_HASHES.includes( currentHash ) ) { + initialFormAction = currentHash === 'register_modal' ? 'register' : 'signin'; + } + if ( config.initialState ) { + initialFormAction = config.initialState; + } + container.setFormAction( initialFormAction, true ); + + document.body.classList.add( 'newspack-signin' ); + modal.setAttribute( 'data-state', 'open' ); + if ( window.newspackReaderActivation?.overlays ) { + modal.overlayId = window.newspackReaderActivation.overlays.add(); + } + + /** Remove the modal hash from the URL if any. */ + if ( SIGN_IN_MODAL_HASHES.includes( window.location.hash.replace( '#', '' ) ) ) { + history.pushState( '', document.title, window.location.pathname + window.location.search ); + } +} diff --git a/assets/reader-activation-auth/google-oauth.js b/assets/reader-activation-auth/google-oauth.js index 92f9c995a4..a9ed7ea112 100644 --- a/assets/reader-activation-auth/google-oauth.js +++ b/assets/reader-activation-auth/google-oauth.js @@ -10,19 +10,17 @@ domReady( function () { [ ...loginsElements ].forEach( element => { element.classList.remove( 'newspack-reader__logins--disabled' ); } ); - const googleLoginElements = document.querySelectorAll( '.newspack-reader__logins__google' ); + const googleLoginElements = document.querySelectorAll( '.newspack-ui__button--google-oauth' ); googleLoginElements.forEach( googleLoginElement => { const googleLoginForm = googleLoginElement.closest( 'form' ); - const redirectInput = googleLoginForm.querySelector( 'input[name="redirect"]' ); const checkLoginStatus = metadata => { fetch( `/wp-json/newspack/v1/login/google/register?metadata=${ JSON.stringify( metadata ) }` ) .then( res => { res .json() .then( ( { message, data } ) => { - const redirect = redirectInput?.value || null; if ( googleLoginForm?.endLoginFlow ) { - googleLoginForm.endLoginFlow( message, res.status, data, redirect ); + googleLoginForm.endLoginFlow( message, res.status, data ); } } ) .catch( error => { diff --git a/assets/reader-activation-auth/index.js b/assets/reader-activation-auth/index.js index ad65d1ad7a..486892d3e2 100644 --- a/assets/reader-activation-auth/index.js +++ b/assets/reader-activation-auth/index.js @@ -1,509 +1,103 @@ -/* globals newspack_ras_config newspack_reader_auth_labels */ - +/* globals newspack_ras_config */ /** - * Internal dependencies. + * Internal dependencies */ -import { domReady, formatTime } from './utils'; - -import './google-oauth'; -import './otp-input'; - -import './style.scss'; - -const SIGN_IN_MODAL_HASHES = [ 'signin_modal', 'register_modal' ]; +import { domReady } from './utils'; +import { SIGN_IN_MODAL_HASHES, getModalContainer, openAuthModal } from './auth-modal.js'; -let currentHash; +import './auth-form.js'; window.newspackRAS = window.newspackRAS || []; - -window.newspackRAS.push( function ( readerActivation ) { +window.newspackRAS.push( readerActivation => { domReady( function () { - const containers = [ ...document.querySelectorAll( '.newspack-reader-auth' ) ]; - const alerts = [ ...document.querySelectorAll( '.woocommerce-message' ) ]; - if ( ! containers.length ) { - return; - } + /** Expose the openAuthModal function to the RAS scope */ + readerActivation._openAuthModal = openAuthModal; - let accountLinks, triggerLinks; - const initLinks = function () { - accountLinks = document.querySelectorAll( '.newspack-reader__account-link' ); - triggerLinks = document.querySelectorAll( - `[data-newspack-reader-account-link],[href="${ newspack_ras_config.account_url }"]` - ); - triggerLinks.forEach( link => { - link.addEventListener( 'click', handleAccountLinkClick ); - } ); - }; - const handleHashChange = function ( ev ) { - currentHash = window.location.hash.replace( '#', '' ); + /** + * Handle hash change. + * + * @param {Event} ev Hash change event. + */ + function handleHashChange( ev ) { + const container = getModalContainer(); + if ( ! container ) { + return; + } + const currentHash = window.location.hash.replace( '#', '' ); if ( SIGN_IN_MODAL_HASHES.includes( currentHash ) ) { if ( ev ) { ev.preventDefault(); } - handleAccountLinkClick(); + container.setFormAction( currentHash === 'register_modal' ? 'register' : 'signin' ); + openAuthModal(); } - }; + } window.addEventListener( 'hashchange', handleHashChange ); handleHashChange(); - initLinks(); - /** Re-initialize links in case the navigation DOM was modified by a third-party. */ - setTimeout( initLinks, 1000 ); /** - * Handle reader changes. + * Handle account link click. + * + * @param {Event} ev Click event. */ - function handleReaderChanges() { - const allContainers = [ ...document.querySelectorAll( '.newspack-reader-auth' ) ]; - /** If no modal login form, bail. */ - if ( ! allContainers.length ) { - return; + function handleAccountLinkClick( ev ) { + ev.preventDefault(); + let callback, redirect; + if ( ev.target.getAttribute( 'data-redirect' ) ) { + redirect = ev.target.getAttribute( 'data-redirect' ); + } else { + redirect = ev.target.getAttribute( 'href' ); } - - allContainers.forEach( container => { - const form = container.querySelector( 'form' ); - const emailInput = container.querySelector( 'input[name="npe"]' ); - const redirectInput = container.querySelector( 'input[name="redirect"]' ); - const reader = readerActivation.getReader(); - - if ( emailInput ) { - emailInput.value = reader?.email || ''; - } - - if ( accountLinks?.length ) { - accountLinks.forEach( link => { - /** If there's a pre-auth, signing in redirects to the reader account. */ - if ( reader?.email && ! reader?.authenticated ) { - link.setAttribute( 'data-redirect', link.getAttribute( 'href' ) ); - redirectInput.value = link.getAttribute( 'href' ); - } else { - link.removeAttribute( 'data-redirect' ); - } - try { - const labels = JSON.parse( link.getAttribute( 'data-labels' ) ); - link.querySelector( '.newspack-reader__account-link__label' ).textContent = - reader?.authenticated ? labels.signedin : labels.signedout; - } catch {} - } ); - } - if ( reader?.authenticated ) { - const messageContentElement = container.querySelector( - '.newspack-reader__auth-form__response__content' - ); - if ( messageContentElement && form ) { - form.replaceWith( messageContentElement.parentNode ); + if ( ! redirect ) { + const closestEl = ev.target.closest( 'a' ); + if ( closestEl ) { + if ( closestEl.getAttribute( 'data-redirect' ) ) { + redirect = closestEl.getAttribute( 'data-redirect' ); + } else { + redirect = closestEl.getAttribute( 'href' ); } } - } ); + } + if ( redirect ) { + callback = () => { + window.location.href = redirect; + }; + } + openAuthModal( { callback } ); } - readerActivation.on( 'reader', handleReaderChanges ); - handleReaderChanges(); /** - * Handle account links. + * Initialize trigger links. */ - function handleAccountLinkClick( ev ) { - const reader = readerActivation.getReader(); - /** If logged in, bail and allow page redirection. */ - if ( reader?.authenticated ) { - return; - } - - const container = document.querySelector( - '.newspack-reader-auth:not(.newspack-reader__auth-form__inline)' + function initializeTriggerLinks() { + const triggerLinks = document.querySelectorAll( + `[data-newspack-reader-account-link],[href="${ newspack_ras_config.account_url }"]` ); - /** If no modal login form, bail. */ - if ( ! container ) { - return; - } - - if ( ev ) { - ev.preventDefault(); - } - - const authLinkMessage = container.querySelector( '[data-has-auth-link]' ); - const emailInput = container.querySelector( 'input[name="npe"]' ); - const redirectInput = container.querySelector( 'input[name="redirect"]' ); - const passwordInput = container.querySelector( 'input[name="password"]' ); - const actionInput = container.querySelector( 'input[name="action"]' ); - - if ( authLinkMessage ) { - if ( readerActivation.hasAuthLink() ) { - authLinkMessage.style.display = 'flex'; - } else { - authLinkMessage.style.display = 'none'; - } - } - - if ( emailInput ) { - emailInput.value = reader?.email || ''; - } - - if ( redirectInput && ev?.target?.getAttribute( 'data-redirect' ) ) { - redirectInput.value = ev.target.getAttribute( 'data-redirect' ); - } - - container.hidden = false; - container.style.display = 'flex'; - - document.body.classList.add( 'newspack-signin' ); - - if ( passwordInput && emailInput?.value && 'pwd' === actionInput?.value ) { - passwordInput.focus(); - } else { - emailInput.focus(); - } - container.overlayId = readerActivation.overlays.add(); - } - - containers.forEach( container => { - const initialForm = container.querySelector( 'form' ); - if ( ! initialForm ) { - return; - } - let form; - /** Workaround AMP's enforced XHR strategy. */ - if ( initialForm.getAttribute( 'action-xhr' ) ) { - initialForm.removeAttribute( 'action-xhr' ); - form = initialForm.cloneNode( true ); - initialForm.replaceWith( form ); - } else { - form = initialForm; - } - - const actionInput = form.querySelector( 'input[name="action"]' ); - const emailInput = form.querySelector( 'input[name="npe"]' ); - const otpCodeInput = form.querySelector( 'input[name="otp_code"]' ); - const passwordInput = form.querySelector( 'input[name="password"]' ); - const submitButtons = form.querySelectorAll( '[type="submit"]' ); - const closeButton = container.querySelector( 'button[data-close]' ); - const backButtons = container.querySelectorAll( '[data-back]' ); - const sendCodeButtons = container.querySelectorAll( '[data-send-code]' ); - - backButtons.forEach( backButton => { - backButton.addEventListener( 'click', function ( ev ) { - ev.preventDefault(); - setFormAction( 'signin', true ); - } ); + triggerLinks.forEach( link => { + link.addEventListener( 'click', handleAccountLinkClick ); } ); + } + initializeTriggerLinks(); + /** Re-initialize links in case the navigation DOM was modified by a third-party. */ + setTimeout( initializeTriggerLinks, 1000 ); - function handleOTPTimer() { - if ( ! sendCodeButtons.length ) { - return; - } - sendCodeButtons.forEach( button => { - button.originalButtonText = button.textContent; - if ( button.otpTimerInterval ) { - clearInterval( button.otpTimerInterval ); - } - const updateButton = () => { - const remaining = readerActivation.getOTPTimeRemaining(); - if ( remaining ) { - button.textContent = `${ button.originalButtonText } (${ formatTime( remaining ) })`; - button.disabled = true; - } else { - button.textContent = button.originalButtonText; - button.disabled = false; - clearInterval( button.otpTimerInterval ); - } - }; - const remaining = readerActivation.getOTPTimeRemaining(); - if ( remaining ) { - button.otpTimerInterval = setInterval( updateButton, 1000 ); - updateButton(); - } - } ); - } - - if ( sendCodeButtons.length ) { - handleOTPTimer(); - sendCodeButtons.forEach( button => { - button.addEventListener( 'click', function ( ev ) { - messageContentElement.innerHTML = ''; - ev.preventDefault(); - form.startLoginFlow(); - const body = new FormData(); - body.set( 'reader-activation-auth-form', 1 ); - body.set( 'npe', emailInput.value ); - body.set( 'action', 'link' ); - readerActivation - .getCaptchaToken() - .then( captchaToken => { - if ( ! captchaToken ) { - return; - } - body.set( 'captcha_token', captchaToken ); - } ) - .catch( e => { - console.log( { e } ); - } ) - .finally( () => { - fetch( form.getAttribute( 'action' ) || window.location.pathname, { - method: 'POST', - headers: { - Accept: 'application/json', - }, - body, - } ) - .then( () => { - messageContentElement.innerHTML = newspack_reader_auth_labels.code_resent; - setFormAction( 'otp' ); - readerActivation.setOTPTimer(); - } ) - .catch( e => { - console.log( e ); - } ) - .finally( () => { - handleOTPTimer(); - form.style.opacity = 1; - submitButtons.forEach( submitButton => { - submitButton.disabled = false; - } ); - } ); - } ); - } ); - } ); - } - - if ( closeButton ) { - closeButton.addEventListener( 'click', function ( ev ) { - ev.preventDefault(); - container.classList.remove( 'newspack-reader__auth-form__visible' ); - container.style.display = 'none'; - document.body.classList.remove( 'newspack-signin' ); - if ( SIGN_IN_MODAL_HASHES.includes( window.location.hash.replace( '#', '' ) ) ) { - history.pushState( - '', - document.title, - window.location.pathname + window.location.search - ); - } - if ( container.overlayId ) { - readerActivation.overlays.remove( container.overlayId ); + /** + * Handle reader changes. + */ + function handleReaderChanges() { + const reader = window.newspackReaderActivation.getReader(); + const accountLinks = document.querySelectorAll( '.newspack-reader__account-link' ); + if ( accountLinks?.length ) { + accountLinks.forEach( link => { + const labels = JSON.parse( link.getAttribute( 'data-labels' ) ); + const labelEl = link.querySelector( '.newspack-reader__account-link__label' ); + if ( labelEl ) { + labelEl.textContent = reader?.authenticated ? labels.signedin : labels.signedout; } } ); } - - const messageContentElement = container.querySelector( - '.newspack-reader__auth-form__response__content' - ); - - const authLinkMessage = container.querySelector( '[data-has-auth-link]' ); - authLinkMessage.hidden = true; - - /** - * Handle auth form action selection. - */ - function setFormAction( action, shouldFocus = false ) { - if ( ! [ 'register', 'signin', 'pwd', 'otp' ].includes( action ) ) { - action = 'signin'; - } - if ( 'otp' === action ) { - if ( ! readerActivation.getOTPHash() ) { - return; - } - const emailAddressElements = container.querySelectorAll( '.email-address' ); - emailAddressElements.forEach( element => { - element.textContent = readerActivation.getReader()?.email || ''; - } ); - // Focus on the first input. - const firstInput = container.querySelector( '.otp-field input[type="text"]' ); - if ( firstInput ) { - firstInput.focus(); - } - } - actionInput.value = action; - container.removeAttribute( 'data-form-status' ); - messageContentElement.innerHTML = ''; - container.querySelectorAll( '[data-action]' ).forEach( item => { - if ( 'none' !== item.style.display ) { - item.prevDisplay = item.style.display; - } - item.style.display = 'none'; - } ); - container.querySelectorAll( '[data-action~="' + action + '"]' ).forEach( item => { - item.style.display = item.prevDisplay; - } ); - try { - const labels = JSON.parse( container.getAttribute( 'data-labels' ) ); - const label = 'register' === action ? labels.register : labels.signin; - container.querySelector( 'h2' ).textContent = label; - } catch {} - if ( shouldFocus ) { - if ( action === 'pwd' && emailInput.value ) { - passwordInput.focus(); - } else if ( action === 'otp' ) { - otpCodeInput.focus(); - } else { - emailInput.focus(); - } - } - } - setFormAction( currentHash === 'register_modal' ? 'register' : 'signin' ); - window.addEventListener( 'hashchange', () => { - if ( SIGN_IN_MODAL_HASHES.includes( currentHash ) ) { - setFormAction( currentHash === 'register_modal' ? 'register' : 'signin' ); - } - } ); - readerActivation.on( 'reader', () => { - if ( readerActivation.getOTPHash() ) { - setFormAction( 'otp' ); - } - } ); - container.querySelectorAll( '[data-set-action]' ).forEach( item => { - item.addEventListener( 'click', function ( ev ) { - ev.preventDefault(); - setFormAction( ev.target.getAttribute( 'data-set-action' ), true ); - } ); - } ); - - form.startLoginFlow = () => { - container.removeAttribute( 'data-form-status' ); - submitButtons.forEach( button => { - button.disabled = true; - } ); - messageContentElement.innerHTML = ''; - form.style.opacity = 0.5; - }; - - form.endLoginFlow = ( message = null, status = 500, data = null, redirect ) => { - container.setAttribute( 'data-form-status', status ); - form.style.opacity = 1; - submitButtons.forEach( button => { - button.disabled = false; - } ); - if ( message ) { - const messageNode = document.createElement( 'p' ); - messageNode.textContent = message; - messageContentElement.appendChild( messageNode ); - } - if ( status === 200 && data ) { - const authenticated = !! data?.authenticated; - readerActivation.setReaderEmail( data.email ); - readerActivation.setAuthenticated( authenticated ); - if ( authenticated ) { - if ( redirect ) { - window.location = redirect; - } - } else { - form.replaceWith( messageContentElement.parentNode ); - } - } - }; - - /** - * Handle auth form submission. - */ - form.addEventListener( 'submit', ev => { - ev.preventDefault(); - form.startLoginFlow(); - - if ( 0 < alerts.length ) { - alerts.forEach( alert => ( alert.style.display = 'none' ) ); - } - - const action = form.action?.value; - - if ( ! form.npe?.value ) { - return form.endLoginFlow( newspack_reader_auth_labels.invalid_email, 400 ); - } - - if ( 'pwd' === action && ! form.password?.value ) { - return form.endLoginFlow( newspack_reader_auth_labels.invalid_password, 400 ); - } - - readerActivation - .getCaptchaToken() - .then( captchaToken => { - if ( ! captchaToken ) { - return; - } - let tokenField = form.captcha_token; - if ( ! tokenField ) { - tokenField = document.createElement( 'input' ); - tokenField.setAttribute( 'type', 'hidden' ); - tokenField.setAttribute( 'name', 'captcha_token' ); - tokenField.setAttribute( 'autocomplete', 'off' ); - form.appendChild( tokenField ); - } - tokenField.value = captchaToken; - } ) - .catch( e => { - form.endLoginFlow( e, 400 ); - } ) - .finally( () => { - const body = new FormData( ev.target ); - if ( ! body.has( 'npe' ) || ! body.get( 'npe' ) ) { - return form.endFlow( newspack_reader_auth_labels.invalid_email, 400 ); - } - if ( 'otp' === action ) { - readerActivation - .authenticateOTP( body.get( 'otp_code' ) ) - .then( data => { - form.endLoginFlow( - data.message, - 200, - data, - currentHash ? '' : body.get( 'redirect' ) - ); - } ) - .catch( data => { - if ( data.expired ) { - setFormAction( 'signin' ); - } - form.endLoginFlow( data.message, 400 ); - } ); - } else { - fetch( form.getAttribute( 'action' ) || window.location.pathname, { - method: 'POST', - headers: { - Accept: 'application/json', - }, - body, - } ) - .then( res => { - container.setAttribute( 'data-form-status', res.status ); - res - .json() - .then( ( { message, data } ) => { - const status = res.status; - let redirect = body.get( 'redirect' ); - if ( status === 200 ) { - readerActivation.setReaderEmail( body.get( 'npe' ) ); - } - /** Redirect every registration to the account page for verification if not coming from a hash link */ - if ( action === 'register' ) { - redirect = newspack_ras_config.account_url; - } - /** Never redirect from hash links. */ - if ( currentHash ) { - redirect = ''; - } - if ( data.action ) { - setFormAction( data.action ); - if ( data.action === 'otp' ) { - readerActivation.setOTPTimer(); - handleOTPTimer(); - } - } else { - form.endLoginFlow( message, status, data, redirect ); - } - } ) - .catch( () => { - form.endLoginFlow(); - } ) - .finally( () => { - form.style.opacity = 1; - submitButtons.forEach( button => { - button.disabled = false; - } ); - } ); - } ) - .catch( () => { - form.endLoginFlow(); - } ); - } - } ); - } ); - } ); + } + window.newspackReaderActivation.on( 'reader', handleReaderChanges ); + handleReaderChanges(); } ); } ); diff --git a/assets/reader-activation-auth/style.scss b/assets/reader-activation-auth/style.scss index 4ec410382a..4da4c4b228 100644 --- a/assets/reader-activation-auth/style.scss +++ b/assets/reader-activation-auth/style.scss @@ -2,6 +2,13 @@ @use '~@wordpress/base-styles/colors' as wp-colors; @use '../shared/scss/mixins'; +.newspack-reader-auth { + .nphp, + input[type='email'].nphp { + @include mixins.visuallyHidden; + } +} + .entry-content .newspack-reader, .newspack-reader { /** @@ -51,373 +58,6 @@ } } - /** - * Sign-In/Register Form - */ - &__auth-form { - display: none; - background: rgba( 0, 0, 0, 0.75 ); - position: fixed; - width: 100% !important; - inset: 0; - justify-content: center; - align-items: center; - z-index: 9999999999; - font-size: 0.8888em; - - @media screen and ( min-width: 600px ) { - font-size: 0.8em; - } - - &__visible { - display: flex !important; - } - - &__inline { - display: block; - background: none; - position: relative; - width: auto; - z-index: auto; - } - - .nphp, - input[type='email'].nphp { - @include mixins.visuallyHidden; - } - - &[data-form-status='200'] { - .newspack-reader__auth-form { - &__response { - text-align: center; - font-size: 1em; - &__icon[data-form-status='200'] { - display: flex; - margin: 0 auto 1em; - border-radius: 100%; - width: 40px; - height: 40px; - justify-content: center; - align-items: center; - color: white; - background: wp-colors.$alert-green; - } - } - } - } - - &[data-form-status='400'], - &[data-form-status='500'] { - .newspack-reader__auth-form { - &__response { - background: color.adjust( wp-colors.$alert-red, $lightness: 51% ); - border-radius: 3px; - display: flex; - justify-content: center; - margin: 0 0 0.4rem; - padding: 0.4rem; - width: 100%; - &__icon[data-form-status='400'] { - display: flex; - flex: 1 1 0; - color: wp-colors.$alert-red; - margin: 0 0.4rem 0 0; - } - &__content { - align-items: center; - display: flex; - flex: 1 1 100%; - } - } - } - } - - @media screen and ( max-width: 744px ) { - align-items: flex-end; - } - - a { - text-decoration: underline; - } - - p { - line-height: 1.5; - margin: 0.8rem 0; - &.small { - margin: 0; - font-size: 0.8125em; - line-height: 1.2307; - a { - color: inherit; - } - } - } - - .components-form { - &__field { - font-size: 1rem; - margin: 0.4rem 0; - } - - &__submit { - flex: 1 1 100%; - font-size: 1rem; - margin: 0; - } - - &__help { - color: wp-colors.$gray-700; - display: flex; - flex: 1 1 100%; - flex-wrap: wrap; - gap: 0.4rem; - justify-content: space-between; - margin: 0.4rem 0 0; - - a { - color: inherit; - } - } - } - - &__wrapper { - position: relative; - width: 100%; - max-width: 544px; - background: white; - max-height: 100vh; - transition: height 125ms ease-in-out; - - .newspack-reader__auth-form__inline & { - margin: auto; - max-width: 780px; - overflow-y: hidden; - } - } - &__have-account { - background-color: #111; - padding: 4px 15px; - margin-bottom: 11px; - padding-top: 6px !important; - padding-bottom: 8px !important; - text-align: center; - width: calc( 100% - 37px ); - @media screen and ( min-width: 600px ) { - width: 100%; - } - &, - a { - color: #fff; - } - a:active, - a:hover { - color: #d6d6d6; - } - } - - &__header { - align-items: baseline; - display: flex; - flex-wrap: wrap; - gap: 0.5em; - justify-content: space-between; - margin: 0 0 1em; - padding-right: 40px; - - .newspack-reader__auth-form__inline & { - padding-right: 0; - } - - @media screen and ( min-width: 600px ) { - padding-right: 0; - } - - h2 { - font-size: 1rem; - line-height: 1.3333; - margin: 0; - - @media screen and ( min-width: 600px ) { - font-size: 1.3125em; - line-height: 1.5238; - } - } - } - - & &__header { - a { - color: wp-colors.$gray-700; - font-size: 0.8125em; - line-height: 1.2307; - - &:active, - &:focus, - &:hover { - text-decoration: none; - } - } - } - - &__content { - padding: 16px; - - @media screen and ( min-width: 600px ) { - padding: 32px; - } - - @media screen and ( min-width: 782px ) { - padding: 47px 64px 64px; - } - - form { - transition: opacity 0.2s ease-in-out; - - > *:last-child { - margin-bottom: 0 !important; - } - } - input[type='text'], - input[type='email'], - input[type='password'] { - width: 100%; - } - .otp-field { - display: flex; - gap: 0.4rem; - justify-content: center; - margin: 0.8rem 0; - input[type='text'] { - flex: 1 1 100%; - font-family: monospace; - font-size: 1.2rem; - max-width: 2.4rem; - text-align: center; - } - } - input[name='otp_code'] { - font-size: 1.2rem; - text-align: center; - font-family: monospace; - } - .newspack-reader__auth-form__inline & { - padding: 0; - } - } - - &__actions { - display: flex; - justify-content: space-between; - flex-wrap: wrap; - - button, - .button, - a.button { - width: 100%; - display: block; - text-align: center; - text-decoration: none; - background: transparent; - border: 1px solid wp-colors.$gray-200; - color: wp-colors.$gray-700; - margin-bottom: 0.4rem; - &:disabled { - background-color: wp-colors.$gray-100; - color: wp-colors.$gray-600; - } - &.secondary { - color: wp-colors.$gray-700; - &:hover, - &:focus { - background-color: wp-colors.$gray-100; - color: wp-colors.$gray-700; - } - } - &.tertiary { - border: 0; - margin: 0; - &:hover, - &:focus { - background-color: transparent; - color: wp-colors.$gray-900; - } - } - &[type='submit'] { - background-color: var( --newspack-cta-color ); - color: var( --newspack-cta-contrast-color ); - transition: background-color 150ms ease-in-out; - border: 0; - &:hover, - &:focus { - background-color: #111; - color: white; - } - } - } - } - - &__response { - &__content { - p { - margin: 0; - } - } - &__icon { - display: none; - } - } - - &__close { - align-items: center; - background: white; - border: none; - border-radius: 3px; - box-shadow: none; - color: inherit; - cursor: pointer; - display: flex; - font-size: inherit; - height: 40px; - justify-content: center; - margin: 8px; - padding: 0; - position: absolute; - right: 0; - top: 7px; - width: 40px; - - @media screen and ( min-width: 600px ) { - height: 30px; - margin: 2px; - width: 30px; - } - - @media screen and ( min-width: 782px ) { - height: 48px; - margin: 8px; - width: 48px; - } - - svg { - fill: currentcolor; - flex: 0 0 24px; - } - - &:focus { - outline: 1.5px solid #111; - outline-offset: 2px; - } - } - - &__terms-text { - color: wp-colors.$gray-700; - font-size: 0.8125em; - line-height: 1.2307 !important; - a { - color: inherit; - } - } - } - /** * Newsletters subscription lists. */ diff --git a/assets/reader-activation/index.js b/assets/reader-activation/index.js index 3dc79bd5b5..2e8a71ab16 100644 --- a/assets/reader-activation/index.js +++ b/assets/reader-activation/index.js @@ -129,8 +129,48 @@ export function getReader() { */ export function hasAuthLink() { const reader = getReader(); - const emailLinkSecret = getCookie( 'np_auth_link' ); - return !! ( reader?.email && emailLinkSecret ); + const otpHash = getCookie( 'np_otp_hash' ); + return !! ( reader?.email && otpHash ); +} + +/** + * Start the authentication modal with an optional custom callback. + * + * @param {Object} config Config. + */ +export function openAuthModal( config = {} ) { + // Set default config. + config = { + ...{ + callback: null, + initialState: null, + skipSuccess: false, + labels: { + signin: { + title: null, + }, + register: { + title: null, + }, + }, + content: null, + }, + ...config, + }; + if ( newspack_ras_config.is_logged_in ) { + if ( config.callback ) { + config.callback(); + } + return; + } + if ( readerActivation._openAuthModal ) { + readerActivation._openAuthModal( config ); + } else { + console.warn( 'Authentication modal not available' ); + if ( config.callback ) { + config.callback(); + } + } } /** @@ -344,6 +384,7 @@ const readerActivation = { setAuthenticated, refreshAuthentication, getReader, + openAuthModal, hasAuthLink, getOTPHash, setOTPTimer, diff --git a/includes/class-magic-link.php b/includes/class-magic-link.php index e43d0f1c9e..a89c687184 100644 --- a/includes/class-magic-link.php +++ b/includes/class-magic-link.php @@ -793,15 +793,15 @@ public static function process_otp_request() { if ( is_wp_error( $authenticated ) ) { if ( 'max_otp_attempts' === $authenticated->get_error_code() ) { - return self::send_otp_request_response( __( "You've reached the maximum attempts for this code. Please try again.", 'newspack' ), false, [ 'expired' => true ] ); + return self::send_otp_request_response( __( "You've reached the maximum attempts for this code, try again.", 'newspack' ), false, [ 'expired' => true ] ); } if ( 'invalid_otp' === $authenticated->get_error_code() ) { - return self::send_otp_request_response( __( 'The code does not match.', 'newspack' ), false ); + return self::send_otp_request_response( __( 'Code not recognized, try again.', 'newspack' ), false ); } } if ( true !== $authenticated ) { - return self::send_otp_request_response( __( 'Unable to authenticated. Please try again.', 'newspack' ), false, [ 'expired' => true ] ); + return self::send_otp_request_response( __( 'Unable to authenticated, try again.', 'newspack' ), false, [ 'expired' => true ] ); } return self::send_otp_request_response( __( 'Login successful!', 'newspack' ), true ); diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 08a99f7d48..ca620d886d 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -84,7 +84,7 @@ public static function return_demo_content() {

"Success" box style

-
+

- Success box style, plus icon + newspack-ui__box__text-center class. + Success box style, plus icon + newspack-ui__box--text-center class.

Plus a little bit of text below it.

@@ -386,7 +386,7 @@ public static function return_demo_content() {
-
+
+
-
- - + +

+ +

+

+
+
+
+ +
+ + + -
- -
-

-
-
- -
- - - - - -

- -

-

- - - -

-

- - - -

- -
- - -
-
- -
-
- -
- -
-
- -

- -
-
- -

- ' - ) - ); - ?> -

-
-
- - -
- - - - - - -
- -

- - - - - - - -

+ +

+ + + +

+
+

+ + +

+ +
+

+ +

+

+ + +

+
+
+ +

- +
+

+ ' + ) + ); + ?> +

+ + + + + + + + + + +
+ +
+
+
+
+

+ +
+
+ +
+ +
+

+ +

+
+
%s', $terms_url, $terms_text ); + } + if ( substr( trim( $terms_text ), -1 ) !== '.' ) { + $terms .= '.'; + } + } + if ( Recaptcha::can_use_captcha() ) { + $terms .= ' ' . Recaptcha::get_terms_text(); + } + return $terms; + } + + /** + * Send the auth form response to the client. * * @param array|WP_Error $data The response to send to the client. * @param string $message Optional custom message. - * @param string $redirect_url Optional custom redirect URL. */ - private static function send_auth_form_response( $data = [], $message = false, $redirect_url = false ) { + private static function send_auth_form_response( $data = [], $message = false ) { $is_error = \is_wp_error( $data ); if ( empty( $message ) ) { $message = $is_error ? $data->get_error_message() : __( 'Login successful!', 'newspack-plugin' ); } - if ( \wp_is_json_request() ) { - \wp_send_json( compact( 'message', 'data' ), \is_wp_error( $data ) ? 400 : 200 ); - exit; - } elseif ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] ) { - \wp_safe_redirect( - \add_query_arg( - [ - 'reader_authenticated' => $is_error ? '0' : '1', - 'message' => $message, - ], - $redirect_url - ) - ); - exit; - } + \wp_send_json( compact( 'message', 'data' ), \is_wp_error( $data ) ? 400 : 200 ); } /** @@ -1302,26 +1318,15 @@ public static function render_third_party_auth() { if ( ! Google_OAuth::is_oauth_configured() ) { return; } - $class = function( ...$parts ) { - array_unshift( $parts, 'logins' ); - return self::get_element_class_name( $parts ); - }; - $classnames = implode( ' ', [ $class(), $class() . '--disabled' ] ); ?> -
- -
-
-
- -
-
-
+ +
+
Create an account instead?', 'newspack-plugin' ) ) ) ); } $payload = [ @@ -1417,28 +1417,28 @@ public static function process_auth_form() { return self::send_auth_form_response( new \WP_Error( 'unauthorized', \is_wp_error( $sent ) ? $sent->get_error_message() : __( 'We encountered an error sending an authentication link. Please try again.', 'newspack-plugin' ) ) ); } $payload['action'] = 'otp'; - return self::send_auth_form_response( $payload, false, $redirect ); + return self::send_auth_form_response( $payload, false ); } else { $payload['action'] = 'pwd'; - return self::send_auth_form_response( $payload, false, $redirect ); + return self::send_auth_form_response( $payload, false ); } case 'pwd': if ( empty( $password ) ) { - return self::send_auth_form_response( new \WP_Error( 'invalid_password', __( 'You must enter a valid password.', 'newspack-plugin' ) ) ); + return self::send_auth_form_response( new \WP_Error( 'invalid_password', __( 'Password not recognized, try again.', 'newspack-plugin' ) ) ); } $user = \wp_authenticate( $user->user_login, $password ); if ( \is_wp_error( $user ) ) { - return self::send_auth_form_response( new \WP_Error( 'unauthorized', __( 'Invalid credentials.', 'newspack-plugin' ) ) ); + return self::send_auth_form_response( new \WP_Error( 'unauthorized', __( 'Password not recognized, try again.', 'newspack-plugin' ) ) ); } $authenticated = self::set_current_reader( $user->ID ); $payload['authenticated'] = \is_wp_error( $authenticated ) ? 0 : 1; - return self::send_auth_form_response( $payload, false, $redirect ); + return self::send_auth_form_response( $payload, false ); case 'link': $sent = Magic_Link::send_email( $user ); if ( true !== $sent ) { return self::send_auth_form_response( new \WP_Error( 'unauthorized', \is_wp_error( $sent ) ? $sent->get_error_message() : __( 'We encountered an error sending an authentication link. Please try again.', 'newspack-plugin' ) ) ); } - return self::send_auth_form_response( $payload, __( 'Please check your inbox for an authentication link.', 'newspack-plugin' ), $redirect ); + return self::send_auth_form_response( $payload, __( 'Please check your inbox for an authentication link.', 'newspack-plugin' ) ); case 'register': $metadata = [ 'registration_method' => 'auth-form' ]; if ( ! empty( $lists ) ) { @@ -1461,8 +1461,18 @@ public static function process_auth_form() { new \WP_Error( 'unauthorized', __( 'Unable to register your account. Try a different email.', 'newspack-plugin' ) ) ); } - $payload['authenticated'] = \absint( $user_id ) ? 1 : 0; - return self::send_auth_form_response( $payload, false, $redirect ); + + $password_url_arg = WooCommerce_My_Account::RESET_PASSWORD_URL_PARAM; + $nonce = wp_create_nonce( $password_url_arg ); + $payload['password_url'] = add_query_arg( + $password_url_arg, + $nonce, + function_exists( 'wc_get_account_endpoint_url' ) ? \wc_get_account_endpoint_url( 'edit-account' ) : home_url() + ); + + $payload['registered'] = 1; + $payload['authenticated'] = 1; + return self::send_auth_form_response( $payload, false ); } } diff --git a/includes/templates/reader-activation/login-form.php b/includes/templates/reader-activation/login-form.php index ea3e58dc4e..0f4f76ef68 100644 --- a/includes/templates/reader-activation/login-form.php +++ b/includes/templates/reader-activation/login-form.php @@ -15,7 +15,10 @@ } \do_action( 'woocommerce_before_customer_login_form' ); - -Reader_Activation::render_auth_form( true ); - +?> +
+ +

+
+ Date: Tue, 30 Jan 2024 18:54:27 +0100 Subject: [PATCH 046/243] chore: fix lint issue --- includes/class-newspack-ui.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index ca620d886d..835af8fcad 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -573,7 +573,7 @@ public static function return_demo_content() { * @return string Modified $content with demo appended. */ public static function load_demo( $content ) { - if ( isset( $_REQUEST['ui-demo'] ) && current_user_can( 'administrator' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( isset( $_REQUEST['ui-demo'] ) && current_user_can( 'manage_options' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $content .= self::return_demo_content(); } return $content; From 717f501e8a68e4687d8929a45ee23f767a502867 Mon Sep 17 00:00:00 2001 From: Adam Boro Date: Wed, 31 Jan 2024 15:32:09 +0100 Subject: [PATCH 047/243] fix: redirect to origin from magic link (see https://github.com/Automattic/newspack-plugin/pull/2894) --- includes/reader-activation/class-reader-activation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index 51cabaebbd..fb36b15cf0 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -1414,7 +1414,7 @@ public static function process_auth_form() { switch ( $action ) { case 'signin': if ( self::is_reader_without_password( $user ) ) { - $sent = Magic_Link::send_email( $user ); + $sent = Magic_Link::send_email( $user, $current_page_url ); if ( true !== $sent ) { return self::send_auth_form_response( new \WP_Error( 'unauthorized', \is_wp_error( $sent ) ? $sent->get_error_message() : __( 'We encountered an error sending an authentication link. Please try again.', 'newspack-plugin' ) ) ); } From 425caea5bbe3349b210f26a977eb3aed0eac15d9 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Wed, 24 Jan 2024 17:12:42 -0500 Subject: [PATCH 048/243] feat(newspack-ui): add spinner styles --- .../scss/elements/forms/_index.scss | 1 + .../scss/elements/forms/_spinner.scss | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 assets/newspack-ui/scss/elements/forms/_spinner.scss diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index a9ca959326..05f3b29fd2 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -1,6 +1,7 @@ @use 'buttons'; @use 'checkbox-radio'; @use 'labels'; +@use 'spinner'; @use 'text-inputs'; // TODO: Find a better home for this stuff. diff --git a/assets/newspack-ui/scss/elements/forms/_spinner.scss b/assets/newspack-ui/scss/elements/forms/_spinner.scss new file mode 100644 index 0000000000..9b24ce3fab --- /dev/null +++ b/assets/newspack-ui/scss/elements/forms/_spinner.scss @@ -0,0 +1,36 @@ +.newspack-ui { + &__spinner { + align-items: center; + background: #fff; + border-radius: 5px; + display: flex; + height: 100%; + justify-content: center; + left: 50%; + opacity: 0.5; + position: absolute; + top: 50%; + transform: translate( -50%, -50% ); + width: 100%; + > span { + animation: spin 1s infinite linear; + border: 2px solid var( --newspack-ui-color-body-bg ); + border-top-color: var( --newspack-ui-color-text-med-contrast ); + border-radius: 50%; + height: 25px; + width: 25px; + } + } +} + +@keyframes spin { + 0% { + transform: rotate( 0deg ); + } + 50% { + transform: rotate( 180deg ); + } + 100% { + transform: rotate( 360deg ); + } +} From 6f5544796e5f8bd84901d68e461eae122ceb51ff Mon Sep 17 00:00:00 2001 From: matticbot Date: Tue, 23 Jan 2024 15:08:13 +0000 Subject: [PATCH 049/243] chore(release): 2.15.0 [skip ci] * add get_recurrence_of_order method ([3232c70](https://github.com/Automattic/newspack-plugin/commit/3232c70d2a5cb3b38f9aa3de55d3e66e3e4464c8)) --- newspack.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/newspack.php b/newspack.php index db4eae4ca7..3f7c89a94b 100644 --- a/newspack.php +++ b/newspack.php @@ -2,7 +2,11 @@ /** * Plugin Name: Newspack * Description: An advanced open-source publishing and revenue-generating platform for news organizations. +<<<<<<< HEAD * Version: 2.16.1 +======= + * Version: 2.15.0 +>>>>>>> 47d7b939 (chore(release): 2.15.0 [skip ci]) * Author: Automattic * Author URI: https://newspack.com/ * License: GPL2 From 55aa0f165851cb8c844f5371541d4aadabff3cb8 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Mon, 29 Jan 2024 10:33:35 -0500 Subject: [PATCH 050/243] feat(newspack-ui): add form error and info styles --- .../newspack-ui/scss/elements/forms/_index.scss | 1 + .../scss/elements/forms/_typography.scss | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 assets/newspack-ui/scss/elements/forms/_typography.scss diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index 05f3b29fd2..66e29dd134 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -3,6 +3,7 @@ @use 'labels'; @use 'spinner'; @use 'text-inputs'; +@use 'typography'; // TODO: Find a better home for this stuff. .newspack-ui { diff --git a/assets/newspack-ui/scss/elements/forms/_typography.scss b/assets/newspack-ui/scss/elements/forms/_typography.scss new file mode 100644 index 0000000000..61123aa701 --- /dev/null +++ b/assets/newspack-ui/scss/elements/forms/_typography.scss @@ -0,0 +1,15 @@ +.newspack-ui { + &__text-error { + color: var( --newspack-ui-color-alert-red ); + display: block; + font-family: var( --newspack-ui-font-family); + font-size: var( --newspack-ui-font-size-small ); + line-height: var( --newspack-ui-line-height-large ); + margin: var( --newspack-ui-spacer-base ) 0 0; + } + + &__text-info { + display: block; + margin: 0; + } +} From c6c774da525953b53db8cd3ec4615911133da0d6 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Tue, 30 Jan 2024 11:30:39 -0500 Subject: [PATCH 051/243] chore(newspack-ui): update form input and error styles --- .../newspack-ui/scss/elements/forms/_index.scss | 1 - .../scss/elements/forms/_typography.scss | 15 --------------- .../scss/elements/woocommerce/_overrides.scss | 6 ++++++ 3 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 assets/newspack-ui/scss/elements/forms/_typography.scss diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index 66e29dd134..05f3b29fd2 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -3,7 +3,6 @@ @use 'labels'; @use 'spinner'; @use 'text-inputs'; -@use 'typography'; // TODO: Find a better home for this stuff. .newspack-ui { diff --git a/assets/newspack-ui/scss/elements/forms/_typography.scss b/assets/newspack-ui/scss/elements/forms/_typography.scss deleted file mode 100644 index 61123aa701..0000000000 --- a/assets/newspack-ui/scss/elements/forms/_typography.scss +++ /dev/null @@ -1,15 +0,0 @@ -.newspack-ui { - &__text-error { - color: var( --newspack-ui-color-alert-red ); - display: block; - font-family: var( --newspack-ui-font-family); - font-size: var( --newspack-ui-font-size-small ); - line-height: var( --newspack-ui-line-height-large ); - margin: var( --newspack-ui-spacer-base ) 0 0; - } - - &__text-info { - display: block; - margin: 0; - } -} diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index 33d8c557ed..a81cc4753e 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -9,4 +9,10 @@ margin: 0 0 var( --newspack-ui-spacer-2 ); } } + + .newspack-ui__input-list { + label { + display: block; + } + } } From d19043b3adfa12c6e77d2b1c2400b525c158378f Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Tue, 30 Jan 2024 16:03:25 -0500 Subject: [PATCH 052/243] feat(newspack-ui): add variation and coupon styles --- assets/newspack-ui/scss/_modals.scss | 68 +++++++++++++++++ .../scss/elements/forms/_index.scss | 8 +- .../scss/elements/woocommerce/_overrides.scss | 75 +++++++++++++++++++ 3 files changed, 149 insertions(+), 2 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 76d1b7d9f2..51b3e3fbf3 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -38,6 +38,74 @@ } } } + &__modal-variation { + .newspack-ui { + &__modal { + &__content { + padding: 24px; + overflow: auto; + border-radius: 5px; + h3 { + font-size: 16px; + margin: 0; + } + p { + font-size: 0.8em; + } + } + } + + &__options { + list-style: none; + display: flex; + flex-wrap: wrap; + gap: 16px; + margin: 0; + padding: 0; + + &__item { + border: 1px solid #ddd; + border-radius: 6px; + text-align: center; + flex: 1 1 100%; + @media ( min-width: 600px ) { + flex: 1 1 30%; + max-width: calc( 33.3333% - 10px ); + &:first-child:nth-last-child( 2 ), + &:first-child:nth-last-child( 2 ) ~ li { + flex: 1 1 40%; + max-width: calc( 50% - 10px ); + } + } + .summary { + font-size: 14px; + padding: 12px; + border-bottom: 1px solid #ddd; + bdi { + display: block; + font-weight: 600; + font-size: 32px; + } + } + .variation { + padding: 12px; + font-size: 14px; + line-height: 1.5; + border-bottom: 1px solid #ddd; + font-weight: 600; + } + form { + padding: 12px; + button { + display: block; + width: 100%; + font-size: 14px; + } + } + } + } + } + } &__modal { // CSS Variables - update button background, with fallbacks to the Newspack UI defaults --newspack-ui-color-button-bg: var( --newspack-ui-color-primary, var( --newspack-ui-color-gray-900 ) ); diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index 05f3b29fd2..faa7b90937 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -39,8 +39,8 @@ } // Form response inline error text. - &__inline-error { - color: var( --newspack-ui-color-alert-red ); + &__inline-error, + &__inline-info { font-size: var( --newspack-ui-font-size-small ); line-height: var( --newspack-ui-line-height-small ); margin: var( --newspack-ui-spacer-base ) 0 var( --newspack-ui-spacer-5 ); @@ -48,4 +48,8 @@ text-decoration: underline; } } + + &__inline-error { + color: var( --newspack-ui-color-alert-red ); + } } diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index a81cc4753e..ba94ebb001 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -15,4 +15,79 @@ display: block; } } + + // Override checkout form heading. + .woocommerce .order-details-summary { + // Top margin not needed in newspack ui modal. + h2 { + margin-top: 0; + } + } + + // Override checkout and billing form headings spacing. + .woocommerce-billing-fields h3, + .woocommerce-additional-fields h3, + .woocommerce-checkout h3, + .woocommerce-form-coupon h3 { + font-size: var(--newspack-ui-font-size-medium); + margin: 1rem 0 !important; + } + + // Override checkout payment method box. + .wc_payment_method .payment_box { + padding: 1rem 0 0; + + ul.wc-saved-payment-methods { + li { + margin-bottom: 16px; + + input { + margin-right: 8px; + } + } + } + + fieldset { + margin-bottom: 8px; + + &:last-child { + margin-bottom: 0; + } + + p.form-row { + display: flex; + align-items: center; + + input { + margin-right: 8px; + } + + label { + margin-bottom: 0; + } + } + } + } + + // Override theme hiding of radio checkbox. + .wc_payment_method input.input-radio[name="payment_method"] { + display: grid; + } + + .woocommerce-form-coupon { + p:first-of-type { + display: flex; + align-items: center; + margin: var(--newspack-ui-spacer-2) 0; + + input { + margin-right: 8px; + } + + button { + margin-bottom: 0; + } + } + } + } From 83e8e6f9e761124dd858654e68f515f088928bdb Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Tue, 30 Jan 2024 16:23:42 -0500 Subject: [PATCH 053/243] feat(newspack-ui): wcs gifting overrides --- .../newspack-ui/scss/elements/woocommerce/_overrides.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index ba94ebb001..bf8225fe78 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -90,4 +90,11 @@ } } + .newspack-wcsg--gift-toggle { + margin-bottom: 0; + + label { + display: flex !important; + } + } } From 78cb42e4889bae40b5e5fc0d7be515b46127e6bd Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Tue, 30 Jan 2024 17:16:39 -0500 Subject: [PATCH 054/243] chore(newspack-ui): fix merge conflit residue --- newspack.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/newspack.php b/newspack.php index 3f7c89a94b..db4eae4ca7 100644 --- a/newspack.php +++ b/newspack.php @@ -2,11 +2,7 @@ /** * Plugin Name: Newspack * Description: An advanced open-source publishing and revenue-generating platform for news organizations. -<<<<<<< HEAD * Version: 2.16.1 -======= - * Version: 2.15.0 ->>>>>>> 47d7b939 (chore(release): 2.15.0 [skip ci]) * Author: Automattic * Author URI: https://newspack.com/ * License: GPL2 From 4bb4075c80ab55207050c37fe1d108595dc6499b Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Thu, 1 Feb 2024 13:23:18 -0500 Subject: [PATCH 055/243] feat(newspack-ui): update payment info text styles --- .../scss/elements/woocommerce/_overrides.scss | 36 ++++++++++++------- .../class-woocommerce-cover-fees.php | 1 - 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index bf8225fe78..606ae01713 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -37,6 +37,10 @@ .wc_payment_method .payment_box { padding: 1rem 0 0; + p { + font-size: var(--newspack-ui-font-size-small); + } + ul.wc-saved-payment-methods { li { margin-bottom: 16px; @@ -48,32 +52,39 @@ } fieldset { - margin-bottom: 8px; + margin-bottom: 12px; &:last-child { margin-bottom: 0; } - p.form-row { - display: flex; - align-items: center; + p { + font-size: var(--newspack-ui-font-size-small); + margin-bottom: 0; - input { - margin-right: 8px; - } + &.form-row { + display: flex; + align-items: flex-start; + + input { + margin-right: 12px; + } - label { - margin-bottom: 0; + label { + margin-bottom: 0; + font-weight: 400; + } } } } } - // Override theme hiding of radio checkbox. - .wc_payment_method input.input-radio[name="payment_method"] { - display: grid; + // Override checkout form terms and condition text. + .woocommerce-terms-and-conditions-wrapper { + font-size: var(--newspack-ui-font-size-small); } + // Override checkout form coupon field. .woocommerce-form-coupon { p:first-of-type { display: flex; @@ -90,6 +101,7 @@ } } + // Override checkout form subscriptions gift toggle. .newspack-wcsg--gift-toggle { margin-bottom: 0; diff --git a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php index fdb9d2adeb..bb05afaf7c 100644 --- a/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php +++ b/includes/reader-revenue/woocommerce/class-woocommerce-cover-fees.php @@ -157,7 +157,6 @@ public static function render_stripe_input() { id="" name="" type="checkbox" - style="margin-right: 8px;" value="1" checked From 481f774ac09557428e6bbb30f10a913cdf57d4cb Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Thu, 1 Feb 2024 13:50:36 -0500 Subject: [PATCH 056/243] feat(newspack-ui): payment method text adjustments --- .../scss/elements/woocommerce/_overrides.scss | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index 606ae01713..85b111468a 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -34,45 +34,52 @@ } // Override checkout payment method box. - .wc_payment_method .payment_box { - padding: 1rem 0 0; - - p { - font-size: var(--newspack-ui-font-size-small); + .wc_payment_method { + span { + font-weight: var( --newspack-ui-font-weight-strong ); } - ul.wc-saved-payment-methods { - li { - margin-bottom: 16px; + .payment_box { + font-weight: normal; + padding: 0; - input { - margin-right: 8px; - } + p { + font-size: var(--newspack-ui-font-size-small); } - } - fieldset { - margin-bottom: 12px; + ul.wc-saved-payment-methods { + li { + margin-bottom: 16px; - &:last-child { - margin-bottom: 0; + input { + margin-right: 8px; + } + } } - p { - font-size: var(--newspack-ui-font-size-small); - margin-bottom: 0; + fieldset { + margin-bottom: 12px; + + &:last-child { + margin-bottom: 0; + } - &.form-row { - display: flex; - align-items: flex-start; + p { + font-size: var(--newspack-ui-font-size-small); + margin-bottom: 0; - input { - margin-right: 12px; - } + &.form-row { + display: flex; + align-items: flex-start; + + input { + margin-right: 12px; + } - label { - margin-bottom: 0; - font-weight: 400; + label { + margin-bottom: 0; + font-weight: normal; + } } } } From 4949fdc672c53f593b4a2ea8f0a6fa230e5d393d Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Mon, 5 Feb 2024 12:51:23 -0500 Subject: [PATCH 057/243] fix(ras-acc): account for null data --- assets/reader-activation-auth/auth-form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/reader-activation-auth/auth-form.js b/assets/reader-activation-auth/auth-form.js index f0b9db6565..fd7681cac0 100644 --- a/assets/reader-activation-auth/auth-form.js +++ b/assets/reader-activation-auth/auth-form.js @@ -234,7 +234,7 @@ window.newspackRAS.push( function ( readerActivation ) { } } else { let labels = newspack_reader_auth_labels.signin; - if ( data.registered ) { + if ( data?.registered ) { labels = newspack_reader_auth_labels.register; } container.setFormAction( 'success' ); From 2c5f3bd3cb1f0ad8c1e6c427a9a2d5f7fe91bf1e Mon Sep 17 00:00:00 2001 From: Derrick Koo Date: Thu, 8 Feb 2024 11:32:55 -0700 Subject: [PATCH 058/243] fix(my-account): fixes for My Account (#2904) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(my-account): fix "renew now" button for subscriptions * fix(wcgs): don’t require shipping fields for virtual products * fix: remove method removed in trunk --- .../class-woocommerce-my-account.php | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/includes/reader-revenue/my-account/class-woocommerce-my-account.php b/includes/reader-revenue/my-account/class-woocommerce-my-account.php index 28015f240b..1d247ed680 100644 --- a/includes/reader-revenue/my-account/class-woocommerce-my-account.php +++ b/includes/reader-revenue/my-account/class-woocommerce-my-account.php @@ -30,6 +30,8 @@ class WooCommerce_My_Account { public static function init() { \add_filter( 'woocommerce_account_menu_items', [ __CLASS__, 'my_account_menu_items' ], 1000 ); \add_filter( 'woocommerce_billing_fields', [ __CLASS__, 'edit_address_required_fields' ] ); + \add_filter( 'wcsg_new_recipient_account_details_fields', [ __CLASS__, 'new_recipient_fields' ] ); + \add_filter( 'wcsg_require_shipping_address_for_virtual_products', '__return_false' ); // Reader Activation mods. if ( Reader_Activation::is_enabled() ) { @@ -331,13 +333,16 @@ public static function is_user_verified() { /** * Redirect to "Account details" if accessing "My Account" directly. - * Do not redirect if the request is a resubscribe request, as resubscribe - * requests do their own redirect to the cart/checkout page. + * Do not redirect if the request is a resubscribe or renewal request, as + * these requests do their own redirect to the cart/checkout page. */ public static function redirect_to_account_details() { - $resubscribe_request = isset( $_REQUEST['resubscribe'] ) ? 'shop_subscription' === get_post_type( absint( $_REQUEST['resubscribe'] ) ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $resubscribe_request = filter_input( INPUT_GET, 'resubscribe', FILTER_SANITIZE_NUMBER_INT ); + $is_resubscribe_request = ! empty( $resubscribe_request ) && 'shop_subscription' === get_post_type( $resubscribe_request ); + $renewal_request = filter_input( INPUT_GET, 'subscription_renewal_early', FILTER_SANITIZE_NUMBER_INT ); + $is_renewal_request = ! empty( $renewal_request ) && 'shop_subscription' === get_post_type( $renewal_request ) && 'true' === filter_input( INPUT_GET, 'subscription_renewal', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); - if ( \is_user_logged_in() && Reader_Activation::is_enabled() && function_exists( 'wc_get_page_permalink' ) && ! $resubscribe_request ) { + if ( \is_user_logged_in() && Reader_Activation::is_enabled() && function_exists( 'wc_get_page_permalink' ) && ! $is_resubscribe_request && ! $is_renewal_request ) { global $wp; $current_url = \home_url( $wp->request ); $my_account_page_permalink = \wc_get_page_permalink( 'myaccount' ); @@ -431,6 +436,29 @@ public static function edit_address_required_fields( $fields ) { return $fields; } + /** + * Ensure that only billing address fields enabled in Reader Revenue settings + * are required for new gift recipient accounts. + * + * See: https://github.com/woocommerce/woocommerce-subscriptions-gifting/blob/trunk/includes/class-wcsg-recipient-details.php#L275 + * + * @param array $fields Address fields. + * @return array + */ + public static function new_recipient_fields( $fields ) { + // Escape hatch to force required shipping address for virtual products. + if ( apply_filters( 'wcsg_require_shipping_address_for_virtual_products', false ) ) { // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + return $fields; + } + $required_fields = Donations::get_billing_fields(); + foreach ( $fields as $field_name => $field_config ) { + if ( ! in_array( 'billing_' . $field_name, $required_fields, true ) ) { + unset( $fields[ $field_name ] ); + } + } + return $fields; + } + /** * WC's page templates hijacking. * From 8b2406762f19cca72a2b9a4ae9b60f7e4acb91c7 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 5 Apr 2024 11:34:32 -0700 Subject: [PATCH 059/243] feat: update component colors, input styles --- assets/newspack-ui/scss/_modals.scss | 13 ++- assets/newspack-ui/scss/elements/_boxes.scss | 6 +- assets/newspack-ui/scss/elements/_icons.scss | 6 +- .../scss/elements/forms/_buttons.scss | 19 ++-- .../scss/elements/forms/_checkbox-radio.scss | 22 ++-- .../scss/elements/forms/_index.scss | 2 +- .../scss/elements/forms/_labels.scss | 4 +- .../scss/elements/forms/_spinner.scss | 2 +- .../scss/elements/forms/_text-inputs.scss | 8 +- .../newspack-ui/scss/variables/_colors.scss | 107 ++++++++++++------ assets/newspack-ui/scss/variables/_index.scss | 2 + assets/newspack-ui/style.scss | 2 +- 12 files changed, 120 insertions(+), 73 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 51b3e3fbf3..caa664d087 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -108,8 +108,8 @@ } &__modal { // CSS Variables - update button background, with fallbacks to the Newspack UI defaults - --newspack-ui-color-button-bg: var( --newspack-ui-color-primary, var( --newspack-ui-color-gray-900 ) ); - --newspack-ui-color-button-text: var( --newspack-ui-color-against-primary, var( --newspack-ui-color-white ) ); + --newspack-ui-color-button-bg: var( --newspack-ui-color-primary, var( --newspack-ui-color-neutral-90 ) ); + --newspack-ui-color-button-text: var( --newspack-ui-color-against-primary, var( --newspack-ui-color-neutral-0 ) ); // Modal styles background: var( --newspack-ui-color-body-bg ); @@ -135,6 +135,7 @@ border-bottom: 1px solid var( --newspack-ui-color-border ); h2 { + font-family: var( --newspack-ui-font-family ); font-size: var( --newspack-ui-font-size-medium ); margin: 0; } @@ -144,13 +145,13 @@ margin: -2px -5px 0 0; // Offsets a padding in the SVG. padding: 0 0 0 8px; background: transparent; - color: var( --newspack-ui-color-text-high-contrast ); + color: var( --newspack-ui-color-neutral-90 ); cursor: pointer; &:focus, &:hover { background: transparent; - color: var( --newspack-ui-color-text-med-contrast ); + color: var( --newspack-ui-color-neutral-70 ); } svg { display: block; @@ -165,8 +166,8 @@ } &__footer { - background: var( --newspack-ui-color-gray-100 ); - color: var( --newspack-ui-color-text-med-contrast ); + background: var( --newspack-ui-color-neutral-5 ); + color: var( --newspack-ui-color-neutral-60 ); font-size: var( --newspack-ui-font-size-extra-small ); line-height: var( --newspack-ui-line-height-small ); a { diff --git a/assets/newspack-ui/scss/elements/_boxes.scss b/assets/newspack-ui/scss/elements/_boxes.scss index 3e7ae09e14..d9953e04b7 100644 --- a/assets/newspack-ui/scss/elements/_boxes.scss +++ b/assets/newspack-ui/scss/elements/_boxes.scss @@ -1,18 +1,18 @@ .newspack-ui { .newspack-ui { &__box { - background: var( --newspack-ui-color-gray-100 ); + background: var( --newspack-ui-color-neutral-5 ); border-radius: var( --newspack-ui-border-radius ); margin-bottom: var( --newspack-ui-spacer-5 ); padding: var( --newspack-ui-spacer-5 ); // Backgrounds & Borders &--success { - background: var( --newspack-ui-color-alert-green-bg ); + background: var( --newspack-ui-color-success-0 ); } &--error { - background: var( --newspack-ui-color-alert-red-bg ); + background: var( --newspack-ui-color-error-0 ); } &--warning { diff --git a/assets/newspack-ui/scss/elements/_icons.scss b/assets/newspack-ui/scss/elements/_icons.scss index 24ea5e1b63..31abe2fc98 100644 --- a/assets/newspack-ui/scss/elements/_icons.scss +++ b/assets/newspack-ui/scss/elements/_icons.scss @@ -10,17 +10,17 @@ width: var( --newspack-ui-spacer-7 ); &--success { - background: var( --newspack-ui-color-alert-green ); + background: var( --newspack-ui-color-success-50 ); color: var( --newspack-ui-color-body-bg ); } &--error { - background: var( --newspack-ui-color-alert-red ); + background: var( --newspack-ui-color-error-50 ); color: var( --newspack-ui-color-body-bg ); } &--warning { - background: var( --newspack-ui-color-alert-yellow ); + background: var( --newspack-ui-color-warning-30 ); color: var( --newspack-ui-color-body-bg ); } } diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index ef1850f925..c68c51615f 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -25,8 +25,8 @@ } &:disabled { - background: var( --newspack-ui-color-gray-100 ) !important; - color: var( --newspack-ui-color-text-med-contrast ) !important; + background: var( --newspack-ui-color-neutral-10 ) !important; + color: var( --newspack-ui-color-neutral-70 ) !important; // cursor: default; } @@ -46,25 +46,24 @@ } &--secondary { - background: transparent; - border: 1px solid var( --newspack-ui-color-border ); - color: var( --newspack-ui-color-text-high-contrast ); + background: var( --newspack-ui-color-neutral-10 ); + color: var( --newspack-ui-color-neutral-90 ); padding: calc( var( --newspack-ui-spacer-2 ) - 1px ) calc( var( --newspack-ui-spacer-3 ) - 1px ); &:hover { - background: var( --newspack-ui-color-gray-100 ); - color: var( --newspack-ui-color-text-high-contrast ); + background: var( --newspack-ui-color-neutral-30 ); + color: var( --newspack-ui-color-neutral-90 ); } } &--tertiary { background: transparent; - color: var( --newspack-ui-color-text-high-contrast ); + color: var( ---newspack-ui-color-neutral-90 ); &:hover { - background: var( --newspack-ui-color-gray-100 ); - color: var( --newspack-ui-color-text-high-contrast ); + background: var( --newspack-ui-color-neutral-10 ); + color: var( --newspack-ui-color-neutral-90 ); } } } diff --git a/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss index 32ad405ed9..8df35ba8d9 100644 --- a/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss +++ b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss @@ -3,15 +3,15 @@ input[type='radio'] { appearance: none; background: white; - border: solid 1px var( --newspack-ui-color-border ); + border: solid 1px var( --newspack-ui-color-input-border ); color: white; cursor: pointer; display: inline-grid; font: inherit; - height: var( --newspack-ui-spacer-5 ) !important; + height: var( --newspack-ui-spacer-4 ) !important; margin: 0; place-content: center; - width: var( --newspack-ui-spacer-5 ) !important; + width: var( --newspack-ui-spacer-4 ) !important; &::before { content: ''; @@ -26,7 +26,7 @@ } &:focus { - outline: 1.5px solid var( --newspack-ui-color-radio-bg ); + outline: 1.5px solid var( --newspack-ui-color-neutral-90 ); outline-offset: 1px; } @@ -37,7 +37,7 @@ } input[type='checkbox'] { - border-radius: var( --newspack-ui-border-radius ); + border-radius: var( --newspack-ui-border-radius-extra-small ); &::before { background: transparent @@ -48,7 +48,7 @@ } &:checked { - background: var( --newspack-ui-color-radio-bg ); + background: var( --newspack-ui-color-neutral-90 ); border-color: transparent; } } @@ -57,15 +57,15 @@ border-radius: 100%; &::before { - background: var( --newspack-ui-color-radio-bg ); + background: var( --newspack-ui-color-neutral-0 ); border-radius: 100%; - height: var( --newspack-ui-spacer-3 ); - margin: 4px; - width: var( --newspack-ui-spacer-3 ); + height: var( --newspack-ui-spacer-base ); + width: var( --newspack-ui-spacer-base ); } &:checked { - border-color: var( --newspack-ui-color-radio-bg ); + background: var( --newspack-ui-color-neutral-90 ); + border-color: var( --newspack-ui-color-neutral-90 ); } } } \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index faa7b90937..4bf551da64 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -50,6 +50,6 @@ } &__inline-error { - color: var( --newspack-ui-color-alert-red ); + color: var( --newspack-ui-color-error-50 ); } } diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss index 68679b747b..62a54ac794 100644 --- a/assets/newspack-ui/scss/elements/forms/_labels.scss +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -26,8 +26,8 @@ // This selector isn't supported in Firefox yet. &:has( input:checked ) { - background: var( --newspack-ui-color-gray-100 ); - border-color: var( --newspack-ui-color-gray-900 ); + background: var( --newspack-ui-color-neutral-5 ); + border-color: var( --newspack-ui-color-neutral-90 ); } + .newspack-ui__input-list { diff --git a/assets/newspack-ui/scss/elements/forms/_spinner.scss b/assets/newspack-ui/scss/elements/forms/_spinner.scss index 9b24ce3fab..c4fdc7f852 100644 --- a/assets/newspack-ui/scss/elements/forms/_spinner.scss +++ b/assets/newspack-ui/scss/elements/forms/_spinner.scss @@ -15,7 +15,7 @@ > span { animation: spin 1s infinite linear; border: 2px solid var( --newspack-ui-color-body-bg ); - border-top-color: var( --newspack-ui-color-text-med-contrast ); + border-top-color: var( --newspack-ui-color-neutral-70 ); border-radius: 50%; height: 25px; width: 25px; diff --git a/assets/newspack-ui/scss/elements/forms/_text-inputs.scss b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss index 32614db5df..c75afedd7e 100644 --- a/assets/newspack-ui/scss/elements/forms/_text-inputs.scss +++ b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss @@ -18,7 +18,7 @@ input[type='zip'], input[type='color'], textarea { - border-color: var( --newspack-ui-color-border ); + border-color: var( --newspack-ui-color-input-border ); border-radius: var( --newspack-ui-border-radius ); display: block; font-family: var( --newspack-ui-font-family); @@ -28,11 +28,13 @@ width: 100%; &:focus { - border-color: var( --newspack-ui-color-text-med-contrast ); + border-color: var( --newspack-ui-color-input-border-focus ); + border-width: 2px; } &:disabled { - // TODO. + background-color: var( --newspack-ui-color-input-background-disabled ); + border-color: var( --newspack-ui-color-input-border-disabled ); } } } \ No newline at end of file diff --git a/assets/newspack-ui/scss/variables/_colors.scss b/assets/newspack-ui/scss/variables/_colors.scss index ee12e1285b..b920143865 100644 --- a/assets/newspack-ui/scss/variables/_colors.scss +++ b/assets/newspack-ui/scss/variables/_colors.scss @@ -1,39 +1,82 @@ :root { - // Grays - notes from the Gutenberg styles. - // TODO: Import from 'wordpress/base-styles/colors' ? - --newspack-ui-color-black: #000; // Use only when you truly need pure black. For UI, use $gray-900. - --newspack-ui-color-gray-900: #1e1e1e; - --newspack-ui-color-gray-800: #2f2f2f; - --newspack-ui-color-gray-700: #757575; // Meets 4.6:1 text contrast against white. - --newspack-ui-color-gray-600: #949494; // Meets 3:1 UI or large text contrast against white. - --newspack-ui-color-gray-400: #ccc; - --newspack-ui-color-gray-300: #ddd; // Used for most borders. - --newspack-ui-color-gray-200: #e0e0e0; // Used sparingly for light borders. - --newspack-ui-color-gray-100: #f0f0f0; // Used for light gray backgrounds. - --newspack-ui-color-white: #fff; - - // Alert colors - --newpsack-ui-color-alert-yellow: #f0b849; - --newspack-ui-color-alert-green: #4ab866; - --newspack-ui-color-alert-red: #cc1818; - // --newpsack-ui-color-alert-yellow-bg: TBD - --newspack-ui-color-alert-green-bg: #edfaef; - --newpsack-ui-color-alert-red-bg: #fcf0f1; + // Neutral: + --newspack-ui-color-neutral-0: #fff; + --newspack-ui-color-neutral-5: #f7f7f7; + --newspack-ui-color-neutral-10: #f0f0f0; + --newspack-ui-color-neutral-20: #e0e0e0; + --newspack-ui-color-neutral-30: #ddd; + --newspack-ui-color-neutral-40: #ccc; + --newspack-ui-color-neutral-50: #949494; + --newspack-ui-color-neutral-60: #6c6c6c; + --newspack-ui-color-neutral-70: #00000070; + --newspack-ui-color-neutral-80: #3e3e3e; + --newspack-ui-color-neutral-90: #1e1e1e; + --newspack-ui-color-neutral-100: #000; + + // Primary: + --newspack-ui-color-primary-0: #f5fdff; + --newspack-ui-color-primary-5: #d6f6ff; + --newspack-ui-color-primary-10: #b4e4ff; + --newspack-ui-color-primary-20: #93ccfd; + --newspack-ui-color-primary-30: #72affb; + --newspack-ui-color-primary-40: #528dfc; + --newspack-ui-color-primary-50: #36f; + --newspack-ui-color-primary-60: #2240d5; + --newspack-ui-color-primary-70: #1522af; + --newspack-ui-color-primary-80: #0b0b8d; + --newspack-ui-color-primary-90: #0d046e; + --newspack-ui-color-primary-100: #0e0052; + + // Secondary: + --newspack-ui-color-secondary-30: #fffff0; + --newspack-ui-color-secondary-40: #ffffd3; + --newspack-ui-color-secondary-50: #ff0; + --newspack-ui-color-secondary-60: #f2f200; + --newspack-ui-color-secondary-70: #e4e400; + + // Success: + --newspack-ui-color-success-0: #edfaef; + --newspack-ui-color-success-5: #b8e6bf; + --newspack-ui-color-success-50: #008a20; + --newspack-ui-color-success-60: #007017; + + // Error: + --newspack-ui-color-error-0: #fcf0f1; + --newspack-ui-color-error-5: #facfd2; + --newspack-ui-color-error-50: #d63638; + --newspack-ui-color-error-60: #b32d2e; + + //Warning: + --newspack-ui-color-warning-0: #fcf9e8; + --newspack-ui-color-warning-5: #f5e6ab; + --newspack-ui-color-warning-30: #dba617; + --newspack-ui-color-warning-40: #bd8600; // Theme variables - from the classic theme; overridden in class-newspack-ui.php for block theme. --newspack-ui-color-primary: var( --newspack-theme-color-primary ); --newspack-ui-color-against-primary: var( --newspack-theme-color-against-primary ); // Specific assignments - general: - --newspack-ui-color-text-high-contrast: var( --newspack-ui-color-gray-900 ); - --newspack-ui-color-text-med-contrast: var( --newspack-ui-color-gray-700 ); - --newspack-ui-color-border: var( --newspack-ui-color-gray-300 ); - --newspack-ui-color-body-bg: var( --newspack-ui-color-white ); - - // Specific assignments - form elements - --newspack-ui-color-button-bg: var( --newspack-ui-color-gray-900 ); - --newspack-ui-color-button-bg-hover: var( --newspack-ui-color-gray-800 ); // TODO: Replace w/correct value. - --newspack-ui-color-button-text: var( --newspack-ui-color-white ); - --newspack-ui-color-button-text-hover: var( --newspack-ui-color-white ); - --newspack-ui-color-radio-bg: var( --newspack-ui-color-gray-900 ); -} \ No newline at end of file + --newspack-ui-color-border: var( --newspack-ui-color-neutral-30 ); + --newspack-ui-color-body-bg: var( --newspack-ui-color-neutral-0 ); + + // Specific assignments - form elements - buttons: + --newspack-ui-color-button-bg: var( --newspack-ui-color-neutral-90 ); + --newspack-ui-color-button-bg-hover: var( --newspack-ui-color-neutral-60 ); + --newspack-ui-color-button-text: var( --newspack-ui-color-neutral-0 ); + --newspack-ui-color-button-text-hover: var( --newspack-ui-color-neutral-0 ); + + // Specific assignments - form elements - inputs: + --newspack-ui-color-input-border: var( --newspack-ui-color-neutral-40 ); + --newspack-ui-color-input-border-focus: var( --newspack-ui-color-neutral-60 ); + --newspack-ui-color-input-border-disabled: var( --newspack-ui-color-neutral-40 ); + --newspack-ui-color-input-background-disabled: var( --newspack-ui-color-neutral-10 ); + + // Alternatives for when prefers-contrast is set to 'more': + @media ( prefers-contrast: more ) { + --newspack-ui-color-input-border: var( --newspack-ui-color-neutral-60 ); + --newspack-ui-color-input-border-focus: var( --newspack-ui-color-neutral-90 ); + --newspack-ui-color-input-border-disabled: var( --newspack-ui-color-neutral-50 ); + --newspack-ui-color-input-background-disabled: var( --newspack-ui-color-neutral-30 ); + } +} diff --git a/assets/newspack-ui/scss/variables/_index.scss b/assets/newspack-ui/scss/variables/_index.scss index a4cb983f00..81c94a47bd 100644 --- a/assets/newspack-ui/scss/variables/_index.scss +++ b/assets/newspack-ui/scss/variables/_index.scss @@ -10,7 +10,9 @@ --newspack-ui-modal-width-small: 368px; // Border radius - not ems because the font size of the element itself caused a cascade. + // TODO: give these better names. --newspack-ui-border-radius: 6px; --newspack-ui-border-radius-small: 5px; + --newspack-ui-border-radius-extra-small: 2px; } \ No newline at end of file diff --git a/assets/newspack-ui/style.scss b/assets/newspack-ui/style.scss index b8e1ac5b26..b14f9d68e5 100644 --- a/assets/newspack-ui/style.scss +++ b/assets/newspack-ui/style.scss @@ -8,7 +8,7 @@ // Need better spot for this &__color-text-gray { - color: var( --newspack-ui-color-text-med-contrast ); + color: var( --newspack-ui-color-neutral-70 ); } // Overrides for theme styles -- to move to theme? From fae0930bfac7b5b3a72ccfe29a4ef0f6d9db2d0d Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 5 Apr 2024 12:58:45 -0700 Subject: [PATCH 060/243] feat: adjust focus styles --- assets/newspack-ui/scss/elements/forms/_text-inputs.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_text-inputs.scss b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss index c75afedd7e..28676364ad 100644 --- a/assets/newspack-ui/scss/elements/forms/_text-inputs.scss +++ b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss @@ -28,8 +28,8 @@ width: 100%; &:focus { - border-color: var( --newspack-ui-color-input-border-focus ); - border-width: 2px; + outline: 2px solid var( --newspack-ui-color-input-border-focus ); + outline-offset: -1px; } &:disabled { From 7cd679c88e59fa57e8d6dea3bf5ff6d028e6447a Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 5 Apr 2024 13:07:59 -0700 Subject: [PATCH 061/243] fix: cleaning up some formatting --- assets/newspack-ui/scss/elements/forms/_buttons.scss | 2 +- assets/newspack-ui/scss/variables/_index.scss | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index c68c51615f..f7e4644633 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -26,7 +26,7 @@ &:disabled { background: var( --newspack-ui-color-neutral-10 ) !important; - color: var( --newspack-ui-color-neutral-70 ) !important; // + color: var( --newspack-ui-color-neutral-70 ) !important; cursor: default; } diff --git a/assets/newspack-ui/scss/variables/_index.scss b/assets/newspack-ui/scss/variables/_index.scss index 81c94a47bd..650c12c511 100644 --- a/assets/newspack-ui/scss/variables/_index.scss +++ b/assets/newspack-ui/scss/variables/_index.scss @@ -14,5 +14,4 @@ --newspack-ui-border-radius: 6px; --newspack-ui-border-radius-small: 5px; --newspack-ui-border-radius-extra-small: 2px; - -} \ No newline at end of file +} From a260cc569e345c99338bdde10a57c6345bb14c0e Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 5 Apr 2024 13:15:42 -0700 Subject: [PATCH 062/243] fix: correct checkbox, radio focus style --- assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss index 8df35ba8d9..7df3cf0629 100644 --- a/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss +++ b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss @@ -28,6 +28,10 @@ &:focus { outline: 1.5px solid var( --newspack-ui-color-neutral-90 ); outline-offset: 1px; + + &:not( :checked ) { + border: 0; + } } &:disabled { From 242456916a45db93fb17045df83e32aa868911ad Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 5 Apr 2024 13:41:31 -0700 Subject: [PATCH 063/243] feat: update border radiuses, some font sizes --- assets/newspack-ui/scss/_modals.scss | 6 +++--- assets/newspack-ui/scss/elements/_boxes.scss | 2 +- assets/newspack-ui/scss/elements/forms/_buttons.scss | 2 +- assets/newspack-ui/scss/elements/forms/_labels.scss | 2 +- assets/newspack-ui/scss/variables/_index.scss | 7 +++---- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index caa664d087..82c64b71ee 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -44,7 +44,7 @@ &__content { padding: 24px; overflow: auto; - border-radius: 5px; + border-radius: var( --newspack-ui-border-radius-small ); h3 { font-size: 16px; margin: 0; @@ -113,7 +113,7 @@ // Modal styles background: var( --newspack-ui-color-body-bg ); - border-radius: var( --newspack-ui-border-radius ); + border-radius: var( --newspack-ui-border-radius-medium ); display: flex; flex-direction: column; max-height: 90vh; @@ -168,7 +168,7 @@ &__footer { background: var( --newspack-ui-color-neutral-5 ); color: var( --newspack-ui-color-neutral-60 ); - font-size: var( --newspack-ui-font-size-extra-small ); + font-size: var( --newspack-ui-font-size-small ); line-height: var( --newspack-ui-line-height-small ); a { text-decoration: underline; diff --git a/assets/newspack-ui/scss/elements/_boxes.scss b/assets/newspack-ui/scss/elements/_boxes.scss index d9953e04b7..e4f943754f 100644 --- a/assets/newspack-ui/scss/elements/_boxes.scss +++ b/assets/newspack-ui/scss/elements/_boxes.scss @@ -2,7 +2,7 @@ .newspack-ui { &__box { background: var( --newspack-ui-color-neutral-5 ); - border-radius: var( --newspack-ui-border-radius ); + border-radius: var( --newspack-ui-border-radius-medium ); margin-bottom: var( --newspack-ui-spacer-5 ); padding: var( --newspack-ui-spacer-5 ); diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index f7e4644633..53b4b92063 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -12,7 +12,7 @@ gap: var( --newspack-ui-spacer-2 ); justify-content: center; line-height: var( --newspack-ui-line-height-large ); - margin-bottom: var( --newspack-ui-spacer-base ); + margin-bottom: var( --newspack-ui-spacer-2 ); padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-3 ); // TODO: correct this transition: background-color 150ms ease-in-out; diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss index 62a54ac794..633d836265 100644 --- a/assets/newspack-ui/scss/elements/forms/_labels.scss +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -19,7 +19,7 @@ &.newspack-ui__input-list { align-items: flex-start; border: 1px solid var( --newspack-ui-color-border ); - border-radius: var( --newspack-ui-border-radius ); + border-radius: var( --newspack-ui-border-radius-medium ); font-weight: normal; margin-bottom: var( --newspack-ui-spacer-5 ); padding: var( --newspack-ui-spacer-3 ); diff --git a/assets/newspack-ui/scss/variables/_index.scss b/assets/newspack-ui/scss/variables/_index.scss index 650c12c511..893a865e74 100644 --- a/assets/newspack-ui/scss/variables/_index.scss +++ b/assets/newspack-ui/scss/variables/_index.scss @@ -6,12 +6,11 @@ :root { // Modal widths --newspack-ui-modal-width-large: 964px; - --newspack-ui-modal-width-medium: 600px; - --newspack-ui-modal-width-small: 368px; + --newspack-ui-modal-width-medium: 632px; + --newspack-ui-modal-width-small: 410px; // Border radius - not ems because the font size of the element itself caused a cascade. - // TODO: give these better names. - --newspack-ui-border-radius: 6px; + --newspack-ui-border-radius-medium: 6px; --newspack-ui-border-radius-small: 5px; --newspack-ui-border-radius-extra-small: 2px; } From 6b972f1f1ce24821ac9ad125686129175e3e7049 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 5 Apr 2024 16:03:03 -0700 Subject: [PATCH 064/243] feat: replace values in modal.scss with variables --- assets/newspack-ui/scss/_modals.scss | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 82c64b71ee..ab0127204f 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -42,11 +42,11 @@ .newspack-ui { &__modal { &__content { - padding: 24px; + padding: var( --newspack-ui-spacer-5 ); overflow: auto; border-radius: var( --newspack-ui-border-radius-small ); h3 { - font-size: 16px; + font-size: var( --newspack-ui-font-size-medium ); margin: 0; } p { @@ -59,13 +59,13 @@ list-style: none; display: flex; flex-wrap: wrap; - gap: 16px; + gap: var( --newspack-ui-spacer-3 ); margin: 0; padding: 0; &__item { - border: 1px solid #ddd; - border-radius: 6px; + border: 1px solid var(--newspack-ui-color-border ); + border-radius: var( --newspack-ui-border-radius-medium ); text-align: center; flex: 1 1 100%; @media ( min-width: 600px ) { @@ -78,28 +78,28 @@ } } .summary { - font-size: 14px; - padding: 12px; - border-bottom: 1px solid #ddd; + font-size: var( --newspack-ui-font-size-small ); + padding: var( --newspack-ui-spacer-2 ); + border-bottom: 1px solid var( --newspack-ui-color-border ); bdi { display: block; font-weight: 600; - font-size: 32px; + font-size: 32px; // TODO: create & replace w/ a variable. } } .variation { - padding: 12px; - font-size: 14px; + padding: var( --newspack-ui-spacer-2 ); + font-size: var( --newspack-ui-font-size-small ); line-height: 1.5; - border-bottom: 1px solid #ddd; + border-bottom: 1px solid var(--newspack-ui-color-border ); font-weight: 600; } form { - padding: 12px; + padding: var( --newspack-ui-spacer-2 ); button { display: block; width: 100%; - font-size: 14px; + font-size: var( --newspack-ui-font-size-small ); } } } @@ -143,7 +143,7 @@ &__close { margin: -2px -5px 0 0; // Offsets a padding in the SVG. - padding: 0 0 0 8px; + padding: 0 0 0 var( --newspack-ui-spacer-base ); background: transparent; color: var( --newspack-ui-color-neutral-90 ); cursor: pointer; From 381e2f88eaa566f46d8d583c925eaf5b413e3ed6 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Mon, 8 Apr 2024 16:37:11 +0100 Subject: [PATCH 065/243] feat: add clamp to font size --- assets/newspack-ui/scss/variables/_fonts.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/newspack-ui/scss/variables/_fonts.scss b/assets/newspack-ui/scss/variables/_fonts.scss index da6e123c16..67c470735f 100644 --- a/assets/newspack-ui/scss/variables/_fonts.scss +++ b/assets/newspack-ui/scss/variables/_fonts.scss @@ -5,7 +5,7 @@ // TODO: the base size for the modals is 16px, with small text/labels at 14px; // The My Account designs appear to use 16px for most labels // Should we have a in-modal vs. non-modal set of font sizes? - --newspack-ui-font-size-large: 20px; + --newspack-ui-font-size-large: clamp(1.125rem, 0.929rem + 0.402vw, 1.25rem); --newspack-ui-font-size-medium: 16px; // modal baseline --newspack-ui-font-size-small: 14px; // modal small --newspack-ui-font-size-extra-small: 12px; // modal extra small From 168a967cb625e1d52b1387334199657df89daf82 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Mon, 8 Apr 2024 17:29:41 +0100 Subject: [PATCH 066/243] feat: add elevation mixin --- assets/newspack-ui/scss/_mixins.scss | 9 +++++++++ assets/newspack-ui/scss/_modals.scss | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 assets/newspack-ui/scss/_mixins.scss diff --git a/assets/newspack-ui/scss/_mixins.scss b/assets/newspack-ui/scss/_mixins.scss new file mode 100644 index 0000000000..0795945d2a --- /dev/null +++ b/assets/newspack-ui/scss/_mixins.scss @@ -0,0 +1,9 @@ +@mixin newspack-ui-elevation($size: 1) { + @if $size == 1 { + box-shadow: 0 1px 10px rgba( 0, 0, 0, 0.07 ); + } @else if $size == 2 { + box-shadow: 0 2px 20px rgba( 0, 0, 0, 0.14 ); + } @else if $size == 3 { + box-shadow: 0 3px 30px rgba( 0, 0, 0, 0.21 ); + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index ab0127204f..a188d63028 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -1,3 +1,5 @@ +@use 'mixins'; + .newspack-ui { &__modal-container { position: fixed; @@ -14,8 +16,8 @@ z-index: 1; inset: 0; opacity: 0; - background: rgba( 0, 0, 0, 0.5 ); - transition: opacity 0.1s linear; + background: rgba( 0, 0, 0, 0.7 ); + transition: opacity 0.125s linear; } .newspack-ui__modal { position: relative; @@ -23,7 +25,8 @@ width: 100%; transform: translateY( 50px ); opacity: 0; - transition: transform 0.1s linear, opacity 0.1s linear; + transition: transform 0.125s linear, opacity 0.125s linear; + @include mixins.newspack-ui-elevation(3); } &[data-state='open'] { z-index: 99999; From 75ffa1d694addc16b303329cbfc2f466fceeab22 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Tue, 9 Apr 2024 11:06:54 -0400 Subject: [PATCH 067/243] feat(ras-acc): update otp transactional email template (#3032) This PR updates the OTP signin transactional email with: - A new footer per RAS-ACC email designs - Use of primary and secondary color backgrounds - Some alignment updates --- assets/other-scripts/emails/style.scss | 5 + includes/emails/class-emails.php | 36 +- .../class-reader-activation-emails.php | 76 ++-- .../reader-activation-emails/otp.php | 401 ++++++++++-------- includes/util.php | 49 +++ 5 files changed, 353 insertions(+), 214 deletions(-) diff --git a/assets/other-scripts/emails/style.scss b/assets/other-scripts/emails/style.scss index 6db5580f8b..9ed863e0cc 100644 --- a/assets/other-scripts/emails/style.scss +++ b/assets/other-scripts/emails/style.scss @@ -1,3 +1,8 @@ .editor-post-title { display: none; } + +.editor-styles-wrapper .block-editor-block-list__layout .wp-block-button { + margin-left: 0 !important; + margin-right: 0 !important; +} diff --git a/includes/emails/class-emails.php b/includes/emails/class-emails.php index b0a5006006..e857d18fa3 100644 --- a/includes/emails/class-emails.php +++ b/includes/emails/class-emails.php @@ -170,20 +170,50 @@ public static function get_email_payload( $config_name, $placeholders = [] ) { $email_config = self::get_email_config_by_type( $config_name ); $html = $email_config['html_payload']; $reply_to_email = $email_config['reply_to_email']; - $placeholders = array_merge( + + if ( class_exists( 'WC' ) ) { + $base_address = WC()->countries->get_base_address(); + $base_city = WC()->countries->get_base_city(); + $base_postcode = WC()->countries->get_base_postcode(); + + $site_address = sprintf( + // translators: formatted store address where 1 is street address, 2 is city, and 3 is postcode. + __( '%1$s, %2$s %3$s', 'newspack' ), + $base_address, + $base_city, + $base_postcode + ); + } else { + $site_address = sprintf( + // translators: formatted store address where 1 is street address, 2 is city, and 3 is postcode. + __( '%1$s, %2$s %3$s', 'newspack' ), + get_option( 'woocommerce_store_address', '' ), + get_option( 'woocommerce_store_city', '' ), + get_option( 'woocommerce_store_postcode', '' ) + ); + } + $placeholders = array_merge( [ [ 'template' => '*CONTACT_EMAIL*', 'value' => sprintf( '%s', $reply_to_email, $reply_to_email ), ], [ - 'template' => '*SITE_URL*', - 'value' => get_site_url(), + 'template' => '*SITE_ADDRESS*', + 'value' => $site_address, ], [ 'template' => '*SITE_LOGO*', 'value' => esc_url( wp_get_attachment_url( get_theme_mod( 'custom_logo' ) ) ), ], + [ + 'template' => '*SITE_TITLE*', + 'value' => get_bloginfo( 'name' ), + ], + [ + 'template' => '*SITE_URL*', + 'value' => get_bloginfo( 'wpurl' ), + ], ], $placeholders ); diff --git a/includes/reader-activation/class-reader-activation-emails.php b/includes/reader-activation/class-reader-activation-emails.php index 49d56f06dd..37330ab27a 100644 --- a/includes/reader-activation/class-reader-activation-emails.php +++ b/includes/reader-activation/class-reader-activation-emails.php @@ -39,20 +39,39 @@ public static function init() { * Register email type. * * @param array $configs Email types. + * + * @return array Email configs. */ public static function add_email_configs( $configs ) { + $available_placeholders = [ + [ + 'label' => __( 'the site base address', 'newspack' ), + 'template' => '*SITE_ADDRESS*', + ], + [ + 'label' => __( 'the site title', 'newspack' ), + 'template' => '*SITE_TITLE*', + ], + [ + 'label' => __( 'the site url', 'newspack' ), + 'template' => '*SITE_URL*', + ], + ]; $configs[ self::EMAIL_TYPES['VERIFICATION'] ] = [ 'name' => self::EMAIL_TYPES['VERIFICATION'], 'label' => __( 'Verification', 'newspack' ), 'description' => __( "Email sent to the reader after they've registered.", 'newspack' ), 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-activation-emails/verification.php', 'editor_notice' => __( 'This email will be sent to a reader after they\'ve registered.', 'newspack' ), - 'available_placeholders' => [ + 'available_placeholders' => array_merge( + $available_placeholders, [ - 'label' => __( 'the verification link', 'newspack' ), - 'template' => '*VERIFICATION_URL*', - ], - ], + [ + 'label' => __( 'the verification link', 'newspack' ), + 'template' => '*VERIFICATION_URL*', + ], + ] + ), ]; $configs[ self::EMAIL_TYPES['MAGIC_LINK'] ] = [ 'name' => self::EMAIL_TYPES['MAGIC_LINK'], @@ -60,12 +79,15 @@ public static function add_email_configs( $configs ) { 'description' => __( 'Email with a login link.', 'newspack' ), 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-activation-emails/magic-link.php', 'editor_notice' => __( 'This email will be sent to a reader when they request a login link.', 'newspack' ), - 'available_placeholders' => [ + 'available_placeholders' => array_merge( + $available_placeholders, [ - 'label' => __( 'the one-time password', 'newspack' ), - 'template' => '*MAGIC_LINK_OTP*', - ], - ], + [ + 'label' => __( 'the one-time password', 'newspack' ), + 'template' => '*MAGIC_LINK_OTP*', + ], + ] + ), ]; $configs[ self::EMAIL_TYPES['OTP_AUTH'] ] = [ 'name' => self::EMAIL_TYPES['OTP_AUTH'], @@ -73,16 +95,19 @@ public static function add_email_configs( $configs ) { 'description' => __( 'Email with a one-time password and login link.', 'newspack' ), 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-activation-emails/otp.php', 'editor_notice' => __( 'This email will be sent to a reader when they request a login link and a one-time password is available.', 'newspack' ), - 'available_placeholders' => [ + 'available_placeholders' => array_merge( + $available_placeholders, [ - 'label' => __( 'the one-time password', 'newspack' ), - 'template' => '*MAGIC_LINK_OTP*', - ], - [ - 'label' => __( 'the login link', 'newspack' ), - 'template' => '*MAGIC_LINK_URL*', - ], - ], + [ + 'label' => __( 'the one-time password', 'newspack' ), + 'template' => '*MAGIC_LINK_OTP*', + ], + [ + 'label' => __( 'the login link', 'newspack' ), + 'template' => '*MAGIC_LINK_URL*', + ], + ] + ), ]; $configs[ self::EMAIL_TYPES['RESET_PASSWORD'] ] = [ 'name' => self::EMAIL_TYPES['RESET_PASSWORD'], @@ -90,12 +115,15 @@ public static function add_email_configs( $configs ) { 'description' => __( 'Email with password reset link.', 'newspack' ), 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-activation-emails/password-reset.php', 'editor_notice' => __( 'This email will be sent to a reader when they request a password creation or reset.', 'newspack' ), - 'available_placeholders' => [ + 'available_placeholders' => array_merge( + $available_placeholders, [ - 'label' => __( 'the password reset link', 'newspack' ), - 'template' => '*PASSWORD_RESET_LINK*', - ], - ], + [ + 'label' => __( 'the password reset link', 'newspack' ), + 'template' => '*PASSWORD_RESET_LINK*', + ], + ] + ), ]; $configs[ self::EMAIL_TYPES['DELETE_ACCOUNT'] ] = [ 'name' => self::EMAIL_TYPES['DELETE_ACCOUNT'], diff --git a/includes/templates/reader-activation-emails/otp.php b/includes/templates/reader-activation-emails/otp.php index 9431512518..5c58ad37b6 100644 --- a/includes/templates/reader-activation-emails/otp.php +++ b/includes/templates/reader-activation-emails/otp.php @@ -5,194 +5,221 @@ * @package Newspack */ +namespace Newspack; + // phpcs:disable WordPressVIPMinimum.Security.Mustache.OutputNotation +[ 'primary_color' => $primary_color, 'secondary_color' => $secondary_color ] = newspack_get_theme_colors(); +[ 'block_markup' => $social_links, 'html_markup' => $social_links_html ] = newspack_get_social_markup(); + +$post_content = ' + +
+ + +

' . __( 'Sign in', 'newspack' ) . '

+ + + +

' . __( 'Use the following code to login to your account:', 'newspack' ) . '

+ + + +

*MAGIC_LINK_OTP*

+ + + +

' . __( 'You can also log into your account by clicking the following button:', 'newspack' ) . '

+ + + + + + + +

' . __( 'Or copy and paste the link in your browser:', 'newspack' ) . ' *MAGIC_LINK_URL*

+ + + +

' . __( 'If you did not request this code, please ignore this email.', 'newspack' ) . '

+
+ + + +
+ + + + +

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack' ), '*SITE_URL*' ) . '

+
+ '; + +$email_html = ' + Sign in
acof-flag

' . __( 'Sign in', 'newspack' ) . '

' . __( 'Use the following code to login to your account:', 'newspack' ) . '

895671

' . __( 'You can also log into your account by clicking the following button:', 'newspack' ) . '

' . __( 'Or copy and paste the link in your browser:', 'newspack' ) . ' *MAGIC_LINK_URL*

' . __( 'If you did not request this code, please ignore this email.', 'newspack' ) . '

' . $social_links_html . '

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack' ), '*SITE_URL*' ) . '

'; + return array( - 'post_title' => __( 'Authorization code', 'newspack' ), - 'post_content' => ' - - -

' . __( 'Welcome back!', 'newspack' ) . '

- - - -

' . __( 'Use the following code to login to your account:', 'newspack' ) . '

- - - -

*MAGIC_LINK_OTP*

- - - -

' . __( 'You can also log into your account by clicking the following button:', 'newspack' ) . '

- - - - - - - -

' . __( 'Or copy and paste the link in your browser:', 'newspack' ) . ' *MAGIC_LINK_URL*

- ', - 'email_html' => 'Authentication link

' . __( 'Welcome back!', 'newspack' ) . '

' . __( 'Use the following code to login to your account:', 'newspack' ) . '

*MAGIC_LINK_OTP*

' . __( 'You can also log into your account by clicking the following button:', 'newspack' ) . '

' . __( 'Or copy and paste the link in your browser:', 'newspack' ) . ' *MAGIC_LINK_URL*

', + 'post_title' => __( 'Sign in', 'newspack' ), + 'post_content' => $post_content, + 'email_html' => $email_html, ); diff --git a/includes/util.php b/includes/util.php index 3ecbdb0ca3..34819e1d3d 100644 --- a/includes/util.php +++ b/includes/util.php @@ -7,6 +7,8 @@ namespace Newspack; +use Newspack\Configuration_Managers; + defined( 'ABSPATH' ) || exit; define( 'NEWSPACK_API_NAMESPACE', 'newspack/v1' ); @@ -492,3 +494,50 @@ function newspack_get_countries() { } return $countries_options; } + +/** + * Get block and html markup for social media services. + * + * @return array An array containing block and html markup for social media services. + */ +function newspack_get_social_markup() { + $cm = Configuration_Managers::configuration_manager_class_for_plugin_slug( 'wordpress_seo' ); + $social_urls = []; + if ( ! is_wp_error( $cm ) ) { + $social_urls = [ + 'facebook' => $cm->get_option( 'facebook_site' ), + 'twitter' => $cm->get_option( 'twitter_site' ), + 'instagram' => $cm->get_option( 'instagram_url' ), + 'youtube' => $cm->get_option( 'youtube_url' ), + ]; + } + + $block_markup = ''; + $html_markup = ''; + foreach ( $social_urls as $service => $url ) { + if ( ! empty( $url ) && ! is_wp_error( $url ) ) { + $block_markup .= ''; + $html_markup .= '
@@ -488,7 +488,7 @@ public static function return_demo_content() { - +
From b5ade4f1e8fe7fabefa686217c24a2ce2b607d8f Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Thu, 18 Apr 2024 10:11:15 -0400 Subject: [PATCH 081/243] feat(ras-acc): add subscription cancellation email template (#3056) This PR adds a new customer-facing subscription cancellation email --- .../readerRevenue/views/emails/index.js | 9 +- includes/emails/class-emails.php | 2 +- .../class-reader-revenue-emails.php | 118 +++--- .../class-woocommerce-connection.php | 90 +++++ .../reader-revenue-emails/cancellation.php | 350 ++++++++++++++++++ .../wizards/class-reader-revenue-wizard.php | 6 +- 6 files changed, 522 insertions(+), 53 deletions(-) create mode 100644 includes/templates/reader-revenue-emails/cancellation.php diff --git a/assets/wizards/readerRevenue/views/emails/index.js b/assets/wizards/readerRevenue/views/emails/index.js index 8615d5a7b2..9594975ae7 100644 --- a/assets/wizards/readerRevenue/views/emails/index.js +++ b/assets/wizards/readerRevenue/views/emails/index.js @@ -87,6 +87,10 @@ const Emails = () => { <> { emails.map( email => { const isActive = email.status === 'publish'; + const notification = + email.type === 'receipt' + ? __( 'This email is not active. The default receipt will be used.', 'newspack-plugin' ) + : __( 'This email is not active.', 'newspack-plugin' ); return ( { { ...( isActive ? {} : { - notification: __( - 'This email is not active. The default receipt will be used.', - 'newspack' - ), + notification, notificationLevel: 'info', } ) } > diff --git a/includes/emails/class-emails.php b/includes/emails/class-emails.php index 24421772a1..7eda05f98f 100644 --- a/includes/emails/class-emails.php +++ b/includes/emails/class-emails.php @@ -269,7 +269,6 @@ public static function send_email( $config_name, $to, $placeholders = [] ) { } } - $switched_locale = \switch_to_locale( \get_user_locale( \wp_get_current_user() ) ); if ( 'string' === gettype( $config_name ) ) { @@ -396,6 +395,7 @@ private static function serialize_email( $type = null, $post_id = 0 ) { $edit_link = str_replace( site_url(), '', $post_link ); } $serialized_email = [ + 'type' => $type, 'label' => $email_config['label'], 'description' => $email_config['description'], 'post_id' => $post_id, diff --git a/includes/reader-revenue/class-reader-revenue-emails.php b/includes/reader-revenue/class-reader-revenue-emails.php index ebb26da9e3..fd596c2ab1 100644 --- a/includes/reader-revenue/class-reader-revenue-emails.php +++ b/includes/reader-revenue/class-reader-revenue-emails.php @@ -14,7 +14,8 @@ */ class Reader_Revenue_Emails { const EMAIL_TYPES = [ - 'RECEIPT' => 'receipt', + 'CANCELLATION' => 'cancellation', + 'RECEIPT' => 'receipt', ]; /** @@ -53,60 +54,87 @@ public static function get_from_email() { * @param array $configs Email types. */ public static function add_email_configs( $configs ) { - $configs[ self::EMAIL_TYPES['RECEIPT'] ] = [ + $available_placeholders = [ + [ + 'label' => __( 'the customer billing name', 'newspack-plugin' ), + 'template' => '*BILLING_NAME*', + ], + [ + 'label' => __( 'the customer billing first name', 'newspack-plugin' ), + 'template' => '*BILLING_FIRST_NAME*', + ], + [ + 'label' => __( 'the customer billing last name', 'newspack-plugin' ), + 'template' => '*BILLING_LAST_NAME*', + ], + [ + 'label' => __( 'the billing frequency (one-time, monthly or annual)', 'newspack-plugin' ), + 'template' => '*BILLING_FREQUENCY*', + ], + [ + 'label' => __( 'the product name', 'newspack-plugin' ), + 'template' => '*PRODUCT_NAME*', + ], + [ + 'label' => __( + 'the contact email to your site (same as the "From" email address)', + 'newspack-plugin' + ), + 'template' => '*CONTACT_EMAIL*', + ], + ]; + $configs[ self::EMAIL_TYPES['RECEIPT'] ] = [ 'name' => self::EMAIL_TYPES['RECEIPT'], 'label' => __( 'Receipt', 'newspack-plugin' ), 'description' => __( "Email sent to the donor after they've donated.", 'newspack-plugin' ), 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-revenue-emails/receipt.php', 'editor_notice' => __( 'This email will be sent to a reader after they contribute to your site.', 'newspack-plugin' ), 'from_email' => self::get_from_email(), - 'available_placeholders' => [ - [ - 'label' => __( 'the customer billing name', 'newspack-plugin' ), - 'template' => '*BILLING_NAME*', - ], - [ - 'label' => __( 'the customer billing first name', 'newspack-plugin' ), - 'template' => '*BILLING_FIRST_NAME*', - ], - [ - 'label' => __( 'the customer billing last name', 'newspack-plugin' ), - 'template' => '*BILLING_LAST_NAME*', - ], + 'available_placeholders' => array_merge( + $available_placeholders, [ - 'label' => __( 'the billing frequency (one-time, monthly or annual)', 'newspack-plugin' ), - 'template' => '*BILLING_FREQUENCY*', - ], - [ - 'label' => __( 'the product name', 'newspack-plugin' ), - 'template' => '*PRODUCT_NAME*', - ], - [ - 'label' => __( 'the payment amount', 'newspack-plugin' ), - 'template' => '*AMOUNT*', - ], - [ - 'label' => __( 'payment date', 'newspack-plugin' ), - 'template' => '*DATE*', - ], - [ - 'label' => __( 'payment method (last four digits of the card used)', 'newspack-plugin' ), - 'template' => '*PAYMENT_METHOD*', - ], - [ - 'label' => __( - 'the contact email to your site (same as the "From" email address)', - 'newspack-plugin' - ), - 'template' => '*CONTACT_EMAIL*', - ], + [ + 'label' => __( 'automatically-generated receipt link', 'newspack-plugin' ), + 'template' => '*RECEIPT_URL*', + ], + [ + 'label' => __( 'the payment amount', 'newspack-plugin' ), + 'template' => '*AMOUNT*', + ], + [ + 'label' => __( 'payment date', 'newspack-plugin' ), + 'template' => '*DATE*', + ], + [ + 'label' => __( 'payment method (last four digits of the card used)', 'newspack-plugin' ), + 'template' => '*PAYMENT_METHOD*', + ], + ] + ), + ]; + $configs[ self::EMAIL_TYPES['CANCELLATION'] ] = [ + 'name' => self::EMAIL_TYPES['CANCELLATION'], + 'label' => __( 'Cancellation', 'newspack-plugin' ), + 'description' => __( "Email sent to the donor after they've cancelled a recurring donation.", 'newspack-plugin' ), + 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-revenue-emails/cancellation.php', + 'editor_notice' => __( 'This email will be sent to a reader after they cancel a recurring donation.', 'newspack-plugin' ), + 'from_email' => self::get_from_email(), + 'available_placeholders' => array_merge( + $available_placeholders, [ - 'label' => __( 'automatically-generated receipt link', 'newspack-plugin' ), - 'template' => '*RECEIPT_URL*', - ], - ], + [ + 'label' => __( 'the recurring donation management url', 'newspack-plugin' ), + 'template' => '*CANCELLATION_URL*', + ], + [ + 'label' => __( 'the recurring donation end date', 'newspack-plugin' ), + 'template' => '*END_DATE*', + ], + ] + ), ]; + return $configs; } } diff --git a/includes/reader-revenue/woocommerce/class-woocommerce-connection.php b/includes/reader-revenue/woocommerce/class-woocommerce-connection.php index 71300e2500..f83ca293b1 100644 --- a/includes/reader-revenue/woocommerce/class-woocommerce-connection.php +++ b/includes/reader-revenue/woocommerce/class-woocommerce-connection.php @@ -33,6 +33,7 @@ public static function init() { \add_filter( 'default_option_woocommerce_subscriptions_allow_switching_nyp_price', [ __CLASS__, 'force_allow_subscription_switching' ], 10, 2 ); \add_filter( 'default_option_woocommerce_subscriptions_enable_retry', [ __CLASS__, 'force_allow_failed_payment_retry' ] ); \add_filter( 'woocommerce_email_enabled_customer_completed_order', [ __CLASS__, 'send_customizable_receipt_email' ], 10, 3 ); + \add_filter( 'woocommerce_email_enabled_cancelled_subscription', [ __CLASS__, 'send_customizable_cancellation_email' ], 10, 3 ); \add_action( 'woocommerce_order_status_completed', [ __CLASS__, 'maybe_update_reader_display_name' ], 10, 2 ); \add_action( 'option_woocommerce_feature_order_attribution_enabled', [ __CLASS__, 'force_disable_order_attribution' ] ); \add_filter( 'woocommerce_related_products', [ __CLASS__, 'disable_related_products' ] ); @@ -522,6 +523,95 @@ public static function send_customizable_receipt_email( $enable, $order, $class return false; } + /** + * Send the customizable cancellation email in addition to WooCommerce Subscription's default. + * We still want to allow WCS to send its cancellation email since this targets the store admin. + * + * @param bool $enable Whether to send the cancellation email. + * @param WC_Subscription $subscription The order object for the cancellation email. + * @param WC_Email $class Instance of the WC_Email class. + * + * @return bool + */ + public static function send_customizable_cancellation_email( $enable, $subscription, $class ) { + // If we don't have a valid subscription, or the customizable email isn't enabled, bail. + if ( ! is_a( $subscription, 'WC_Subscription' ) || ! Emails::can_send_email( Reader_Revenue_Emails::EMAIL_TYPES['CANCELLATION'] ) ) { + return $enable; + } + + $frequencies = [ + 'month' => __( 'Monthly', 'newspack-plugin' ), + 'year' => __( 'Yearly', 'newspack-plugin' ), + ]; + $product_map = []; + foreach ( $frequencies as $frequency => $label ) { + $product_id = Donations::get_donation_product( $frequency ); + if ( $product_id ) { + $product_map[ $product_id ] = $label; + } + } + + $items = $subscription->get_items(); + $item = array_shift( $items ); + $is_donation = Donations::is_donation_product( $item->get_product_id() ); + + // Replace content placeholders. + $placeholders = [ + [ + 'template' => '*BILLING_NAME*', + 'value' => trim( $subscription->get_billing_first_name() . ' ' . $subscription->get_billing_last_name() ), + ], + [ + 'template' => '*BILLING_FIRST_NAME*', + 'value' => $subscription->get_billing_first_name(), + ], + [ + 'template' => '*BILLING_LAST_NAME*', + 'value' => $subscription->get_billing_last_name(), + ], + [ + 'template' => '*BILLING_FREQUENCY*', + 'value' => $product_map[ $item->get_product_id() ] ?? __( 'One-time', 'newspack-plugin' ), + ], + [ + 'template' => '*PRODUCT_NAME*', + 'value' => $item->get_name(), + ], + [ + 'template' => '*END_DATE*', + 'value' => wcs_format_datetime( wcs_get_datetime_from( $subscription->get_date( 'end' ) ) ), + ], + [ + 'template' => '*BUTTON_TEXT*', + 'value' => $is_donation ? __( 'Restart Donation', 'newspack-plugin' ) : __( 'Restart Subscription', 'newspack-plugin' ), + ], + [ + 'template' => '*CANCELLATION_DATE*', + 'value' => wcs_format_datetime( wcs_get_datetime_from( $subscription->get_date( 'cancelled' ) ) ), + ], + [ + 'template' => '*CANCELLATION_TITLE*', + 'value' => $is_donation ? __( 'Donation Cancelled', 'newspack-plugin' ) : __( 'Subscription Cancelled', 'newspack-plugin' ), + ], + [ + 'template' => '*CANCELLATION_TYPE*', + 'value' => $is_donation ? __( 'recurring donation', 'newspack-plugin' ) : __( 'subscription', 'newspack-plugin' ), + ], + [ + 'template' => '*SUBSCRIPTION_URL*', + 'value' => $subscription->get_view_order_url(), + ], + ]; + + $sent = Emails::send_email( + Reader_Revenue_Emails::EMAIL_TYPES['CANCELLATION'], + $subscription->get_billing_email(), + $placeholders + ); + + return $enable; + } + /** * If the reader completes an order, check if they have a generic display name. * If they do and they also have a billing first and/or last name, we can upgrade diff --git a/includes/templates/reader-revenue-emails/cancellation.php b/includes/templates/reader-revenue-emails/cancellation.php new file mode 100644 index 0000000000..a90d3632f2 --- /dev/null +++ b/includes/templates/reader-revenue-emails/cancellation.php @@ -0,0 +1,350 @@ + +

*CANCELLATION_TITLE*

+ + + +

' . sprintf( /* Translators: 1: the cancellation type (subscription or recurring donation). 2: the site title. */ __( 'This is to confirm the cancellation of your %1$s to %2$s. We\'re sorry to see you go! If you\'d like to restart your %1$s, you can do so by clicking the button below.', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_TITLE*' ) . '

+ + + +
+ + + +
+ + + +

' . sprintf( /* Translators: s: site admin email address. */ __( 'If you have any questions, you can reach us at %s. We appreciate your support', 'newspack-plugin' ), '*CONTACT_EMAIL*' ) . '

+ '; + +$email_html = ' + + + + *CANCELLATION_TITLE* + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + + + +
+ +

*CANCELLATION_TITLE*

+ +
+ +
+ +
+ + +
+ +
+ + + + + +
+ + + + + + + +
+ + +
+ + + + + + + +
+ + + + + + + + + +
+ +

' . sprintf( /* Translators: 1: the cancellation type (subscription or recurring donation). 2: the site title. */ __( 'This is to confirm the cancellation of your %1$s to %2$s. We\'re sorry to see you go! If you\'d like to restart your %1$s, you can do so by clicking the button below.', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_TITLE*' ) . '

+ +
+ +
+ +
+ + +
+ +
+ + + +
+
+ + + + + + + +
+ + +
+ + + + + + + +
+ + + + + + + + + +
+ +

' . sprintf( /* Translators: s: site admin email address. */ __( 'If you have any questions, you can reach us at %s. We appreciate your support!', 'newspack-plugin' ), '*CONTACT_EMAIL*' ) . '

+ +
+ +
+ +
+ + +
+ +
+ +
+ +'; + +return array( + 'post_title' => __( 'Subscription Cancelled', 'newspack' ), + 'post_content' => $post_content, + 'email_html' => $email_html, +); diff --git a/includes/wizards/class-reader-revenue-wizard.php b/includes/wizards/class-reader-revenue-wizard.php index 5955219d3c..e151e2105b 100644 --- a/includes/wizards/class-reader-revenue-wizard.php +++ b/includes/wizards/class-reader-revenue-wizard.php @@ -531,7 +531,7 @@ public function api_get_donation_settings() { /** - * Reset reader activation email template. + * Reset donation email template. * We acheive this by trashing the email template post. * * @param WP_REST_Request $request Request object. @@ -565,7 +565,7 @@ public function api_reset_donation_email( $request ) { ); } - return rest_ensure_response( Emails::get_emails( [ Reader_Revenue_Emails::EMAIL_TYPES['RECEIPT'] ], false ) ); + return rest_ensure_response( Emails::get_emails( array_values( Reader_Revenue_Emails::EMAIL_TYPES ), false ) ); } @@ -609,7 +609,7 @@ public function enqueue_scripts_and_styles() { 'newspack-reader-revenue-wizard', 'newspack_reader_revenue', [ - 'emails' => Emails::get_emails( [ Reader_Revenue_Emails::EMAIL_TYPES['RECEIPT'] ], false ), + 'emails' => Emails::get_emails( array_values( Reader_Revenue_Emails::EMAIL_TYPES ), false ), 'email_cpt' => Emails::POST_TYPE, 'salesforce_redirect_url' => Salesforce::get_redirect_url(), 'can_use_name_your_price' => Donations::can_use_name_your_price(), From 6a2d73172e5e4f796490025bd12de9e0226be129 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Thu, 18 Apr 2024 17:04:17 +0100 Subject: [PATCH 082/243] feat: add Button icon --- assets/newspack-ui/scss/elements/_icons.scss | 4 +- .../scss/elements/forms/_buttons.scss | 25 +++++++++--- .../newspack-ui/scss/variables/_spacing.scss | 7 ++-- includes/class-newspack-ui.php | 40 +++++++++++++++++++ 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/assets/newspack-ui/scss/elements/_icons.scss b/assets/newspack-ui/scss/elements/_icons.scss index 31abe2fc98..6c4dba8706 100644 --- a/assets/newspack-ui/scss/elements/_icons.scss +++ b/assets/newspack-ui/scss/elements/_icons.scss @@ -4,10 +4,10 @@ align-items: center; border-radius: 100%; display: flex; - height: var( --newspack-ui-spacer-7 ); + height: var( --newspack-ui-spacer-8 ); justify-content: center; margin: 0 auto var( --newspack-ui-spacer-2 ); - width: var( --newspack-ui-spacer-7 ); + width: var( --newspack-ui-spacer-8 ); &--success { background: var( --newspack-ui-color-success-50 ); diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index 56be4db1e7..2dadcbee04 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -30,11 +30,7 @@ outline-offset: 1px; } - &--wide { - display: flex; - width: 100%; - } - + // Styles &--primary { background: var( --newspack-ui-color-button-bg ); color: var( --newspack-ui-color-button-text ); @@ -132,5 +128,24 @@ color: var( --newspack-ui-color-neutral-0 ) !important; } } + + // Wide + &--wide { + display: flex; + width: 100%; + } + + // Icon-only + &--icon { + display: grid; + height: var( --newspack-ui-spacer-7 ); // This is the XS size, we will need S, and M + padding: 0; + place-items: center; + width: var( --newspack-ui-spacer-7 ); + + svg { + fill: currentcolor; + } + } } } diff --git a/assets/newspack-ui/scss/variables/_spacing.scss b/assets/newspack-ui/scss/variables/_spacing.scss index 7579ddb07d..4e20b981c4 100644 --- a/assets/newspack-ui/scss/variables/_spacing.scss +++ b/assets/newspack-ui/scss/variables/_spacing.scss @@ -6,7 +6,8 @@ --newspack-ui-spacer-4: calc( var( --newspack-ui-spacer-base ) * 2.5 ); // 20px --newspack-ui-spacer-5: calc( var( --newspack-ui-spacer-base ) * 3 ); // 24px --newspack-ui-spacer-6: calc( var( --newspack-ui-spacer-base ) * 4 ); // 32px - TODO: clamp? - --newspack-ui-spacer-7: calc( var( --newspack-ui-spacer-base ) * 5 ); // 40px - TODO: clamp? - --newspack-ui-spacer-8: calc( var( --newspack-ui-spacer-base ) * 6 ); // 48px - TODO: clamp? - --newspack-ui-spacer-9: calc( var( --newspack-ui-spacer-base ) * 8 ); // 64px - TODO: clamp? + --newspack-ui-spacer-7: calc( var( --newspack-ui-spacer-base ) * 4.5 ); // 36px - TODO: clamp? + --newspack-ui-spacer-8: calc( var( --newspack-ui-spacer-base ) * 5 ); // 40px - TODO: clamp? + --newspack-ui-spacer-9: calc( var( --newspack-ui-spacer-base ) * 6 ); // 48px - TODO: clamp? + --newspack-ui-spacer-10: calc( var( --newspack-ui-spacer-base ) * 8 ); // 64px - TODO: clamp? } \ No newline at end of file diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 7c16efb48f..d90984855c 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -294,6 +294,46 @@ public static function return_demo_content() {
+

Buttons Icon

+

Uses the same classes as the newspack-ui__button but we add an extra class to it newspack-ui__button--icon

+ + + + + + + + +
+

Modals

From 0dfcd183c8dd993cb072759570534c0f66ca900a Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Thu, 18 Apr 2024 17:11:34 +0100 Subject: [PATCH 083/243] fix: modal header stickyness --- assets/newspack-ui/scss/_modals.scss | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 4db2bcb592..55345784a1 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -126,16 +126,18 @@ } &__header { - display: flex; - position: sticky; align-items: center; - justify-content: space-between; background: var( --newspack-ui-color-body-bg ); border-bottom: 1px solid var( --newspack-ui-color-border ); + display: flex; + justify-content: space-between; + position: sticky; + top: 0; h2 { font-family: var( --newspack-ui-font-family ); font-size: var( --newspack-ui-font-size-s ); + line-height: var( --newspack-ui-line-height-s ); margin: 0; } } From 58424b95d92e3ee340667af7b0b7ccf9d79f49c2 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Thu, 18 Apr 2024 12:12:36 -0400 Subject: [PATCH 084/243] feat(ras-acc): dynamically set otp email text color (#3033) This PR adjusts email text for the default otp email template to either white or black depending on background color --- includes/emails/class-emails.php | 52 +++ .../reader-activation-emails/otp.php | 431 ++++++++++-------- includes/util.php | 115 ++++- 3 files changed, 389 insertions(+), 209 deletions(-) diff --git a/includes/emails/class-emails.php b/includes/emails/class-emails.php index 7eda05f98f..cbecdf4204 100644 --- a/includes/emails/class-emails.php +++ b/includes/emails/class-emails.php @@ -29,6 +29,7 @@ public static function init() { add_filter( 'newspack_newsletters_email_editor_cpts', [ __CLASS__, 'register_email_cpt_with_email_editor' ] ); add_filter( 'newspack_newsletters_allowed_editor_actions', [ __CLASS__, 'register_scripts_enqueue_with_email_editor' ] ); add_action( 'update_option_theme_mods_' . get_template(), [ __CLASS__, 'maybe_update_email_templates' ], 10, 2 ); + add_action( 'admin_head', [ __CLASS__, 'inject_dynamic_email_template_styles' ] ); } /** @@ -646,8 +647,59 @@ public static function maybe_update_email_templates( $previous_value, $updated_v foreach ( $templates as $template ) { wp_update_post( [ 'ID' => $template->ID ] ); } + + if ( class_exists( 'Newspack_Newsletters' ) ) { + // Update newsletters color palette option so emails reflect the new colors. + $request = new \WP_REST_Request( 'POST', '/newspack-newsletters/v1/color-palette' ); + $request->set_body( + wp_json_encode( + [ + 'primary' => $updated_value['primary_color_hex'], + 'secondary' => $updated_value['secondary_color_hex'], + 'primary-text' => newspack_get_color_contrast( $updated_value['primary_color_hex'] ), + 'secondary-text' => newspack_get_color_contrast( $updated_value['secondary_color_hex'] ), + ] + ) + ); + + $response = rest_do_request( $request ); + + if ( $response->is_error() ) { + Logger::error( 'Error updating newsletters color palette: ' . $response->as_error()->get_error_message() ); + } + } } } + + /** + * Inject dynamic email template styles for dynamic text colors in the editor. + * + * @return void + */ + public static function inject_dynamic_email_template_styles() { + if ( get_post_type() !== self::POST_TYPE ) { + return; + } + + [ + 'primary_text_color' => $primary_text_color, + 'secondary_text_color' => $secondary_text_color, + ] = newspack_get_theme_colors(); + + ?> + + $primary_color, 'secondary_color' => $secondary_color ] = newspack_get_theme_colors(); -[ 'block_markup' => $social_links, 'html_markup' => $social_links_html ] = newspack_get_social_markup(); +[ + 'primary_color' => $primary_color, + 'primary_text_color' => $primary_text_color, + 'secondary_color' => $secondary_color, + 'secondary_text_color' => $secondary_text_color, +] = newspack_get_theme_colors(); -$post_content = ' - -
+[ + 'block_markup' => $social_links, + 'html_markup' => $social_links_html +] = newspack_get_social_markup( $primary_text_color ); + +$post_content = + // Main body. + ' + + ' . - -
- + // Footer. + ' + '; $email_html = ' - Sign in
acof-flag

' . __( 'Sign in', 'newspack' ) . '

' . __( 'Use the following code to login to your account:', 'newspack' ) . '

895671

' . __( 'You can also log into your account by clicking the following button:', 'newspack' ) . '

' . __( 'Or copy and paste the link in your browser:', 'newspack' ) . ' *MAGIC_LINK_URL*

' . __( 'If you did not request this code, please ignore this email.', 'newspack' ) . '

' . $social_links_html . '

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack' ), '*SITE_URL*' ) . '

'; + + + ' . __( 'Sign in', 'newspack-plugin' ) . ' + + + + + + + + + + + + + + +
+
+
+
+
acof-flag
+
+

' . __( 'Sign in', 'newspack-plugin' ) . '

+
+

' . __( 'Use the following code to login to your account:', 'newspack-plugin' ) . '

+
+

*MAGIC_LINK_OTP*

+
+

' . __( 'You can also log into your account by clicking the following button:', 'newspack-plugin' ) . '

+ +
+

' . __( 'Or copy and paste the link in your browser:', 'newspack-plugin' ) . ' *MAGIC_LINK_URL*

+
+

' . __( 'If you did not request this code, please ignore this email.', 'newspack-plugin' ) . '

+
+
+
' . $social_links_html . '
+
+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+
+ + '; return array( - 'post_title' => __( 'Sign in', 'newspack' ), + 'post_title' => __( 'Sign in', 'newspack-plugin' ), 'post_content' => $post_content, 'email_html' => $email_html, ); diff --git a/includes/util.php b/includes/util.php index 34819e1d3d..49e03f27e6 100644 --- a/includes/util.php +++ b/includes/util.php @@ -495,49 +495,116 @@ function newspack_get_countries() { return $countries_options; } +/** + * Pick either white or black, whatever has sufficient contrast with the color being passed to it. + * (Copied from the Newspack theme: https://github.com/Automattic/newspack-theme/blob/6dc4e89a65c465abdd207d990e313921f2972a9a/newspack-theme/inc/template-functions.php#L547) + * + * @param string $hex Hexidecimal value of the color to adjust. + * + * @return string Either black or white hexidecimal values. + * + * @ref https://stackoverflow.com/questions/1331591/given-a-background-color-black-or-white-text + */ +function newspack_get_color_contrast( $hex ) { + // hex RGB. + $r1 = hexdec( substr( $hex, 1, 2 ) ); + $g1 = hexdec( substr( $hex, 3, 2 ) ); + $b1 = hexdec( substr( $hex, 5, 2 ) ); + // Black RGB. + $black_color = '#000'; + $r2_black_color = hexdec( substr( $black_color, 1, 2 ) ); + $g2_black_color = hexdec( substr( $black_color, 3, 2 ) ); + $b2_black_color = hexdec( substr( $black_color, 5, 2 ) ); + // Calc contrast ratio. + $l1 = 0.2126 * pow( $r1 / 255, 2.2 ) + + 0.7152 * pow( $g1 / 255, 2.2 ) + + 0.0722 * pow( $b1 / 255, 2.2 ); + $l2 = 0.2126 * pow( $r2_black_color / 255, 2.2 ) + + 0.7152 * pow( $g2_black_color / 255, 2.2 ) + + 0.0722 * pow( $b2_black_color / 255, 2.2 ); + $contrast_ratio = 0; + if ( $l1 > $l2 ) { + $contrast_ratio = (int) ( ( $l1 + 0.05 ) / ( $l2 + 0.05 ) ); + } else { + $contrast_ratio = (int) ( ( $l2 + 0.05 ) / ( $l1 + 0.05 ) ); + } + if ( $contrast_ratio > 5 ) { + // If contrast is more than 5, return black color. + return 'black'; + } else { + // if not, return white color. + return 'white'; + } +} + +/** + * Get theme primary and secondary colors or defaults if none present. + * + * @return array An array containing primary and secondary colors. + */ +function newspack_get_theme_colors() { + $default_primary_color = function_exists( 'newspack_get_primary_color' ) ? newspack_get_primary_color() : '#3366ff'; + $default_secondary_color = function_exists( 'newspack_get_secondary_color' ) ? newspack_get_secondary_color() : '#f0f0f0'; + $primary_color = get_theme_mod( 'primary_color_hex', $default_primary_color ); + $secondary_color = get_theme_mod( 'secondary_color_hex', $default_secondary_color ); + + return [ + 'primary_color' => $primary_color, + 'secondary_color' => $secondary_color, + 'primary_text_color' => newspack_get_color_contrast( $primary_color ), + 'secondary_text_color' => newspack_get_color_contrast( $secondary_color ), + ]; +} + /** * Get block and html markup for social media services. * + * @param string $color The color to use for the social media icons. + * * @return array An array containing block and html markup for social media services. */ -function newspack_get_social_markup() { +function newspack_get_social_markup( $color = 'white' ) { $cm = Configuration_Managers::configuration_manager_class_for_plugin_slug( 'wordpress_seo' ); $social_urls = []; + $markup = [ + 'block_markup' => '', + 'html_markup' => '', + ]; + if ( ! is_wp_error( $cm ) ) { $social_urls = [ 'facebook' => $cm->get_option( 'facebook_site' ), 'twitter' => $cm->get_option( 'twitter_site' ), 'instagram' => $cm->get_option( 'instagram_url' ), + 'linkedin' => $cm->get_option( 'linkedin_url' ), 'youtube' => $cm->get_option( 'youtube_url' ), ]; } - $block_markup = ''; - $html_markup = ''; foreach ( $social_urls as $service => $url ) { if ( ! empty( $url ) && ! is_wp_error( $url ) ) { - $block_markup .= ''; - $html_markup .= '
'; + $markup['html_markup'] .= ' + + + + + + +
+ '; } } - return [ - 'block_markup' => $block_markup, - 'html_markup' => $html_markup, - ]; -} - -/** - * Get theme primary and secondary colors or defaults if none present. - * - * @return array An array containing primary and secondary colors. - */ -function newspack_get_theme_colors() { - $default_primary_color = function_exists( 'newspack_get_primary_color' ) ? newspack_get_primary_color() : '#3366ff'; - $default_secondary_color = function_exists( 'newspack_get_secondary_color' ) ? newspack_get_secondary_color() : '#f0f0f0'; - - return [ - 'primary_color' => get_theme_mod( 'primary_color_hex', $default_primary_color ), - 'secondary_color' => get_theme_mod( 'secondary_color_hex', $default_secondary_color ), - ]; + return $markup; } From 2ee4d9d1e4abfec28824c5b49be2125ab5765acf Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Thu, 18 Apr 2024 17:14:44 +0100 Subject: [PATCH 085/243] fix(demo): modal class width --- includes/class-newspack-ui.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index d90984855c..68c676157f 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -576,7 +576,7 @@ public static function return_demo_content() {
-
+

Auth Modal Contents Default

From bccb560354f5f36fb2f29e6193562c83a9b74b0f Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Thu, 18 Apr 2024 13:51:32 -0400 Subject: [PATCH 086/243] feat(ras-acc): add faq section to otp email (#3034) This PR adds an FAQ section to the otp email template --- includes/class-magic-link.php | 11 +++++ .../class-reader-activation-emails.php | 4 ++ .../reader-activation-emails/otp.php | 49 +++++++++++++------ 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/includes/class-magic-link.php b/includes/class-magic-link.php index 1d12bfb19b..22b8241673 100644 --- a/includes/class-magic-link.php +++ b/includes/class-magic-link.php @@ -413,6 +413,12 @@ public static function send_email( $user, $redirect_to = '', $use_otp = true ) { if ( \is_wp_error( $token_data ) ) { return $token_data; } + + $key = \get_password_reset_key( $user ); + if ( is_wp_error( $key ) ) { + return $key; + } + $url = \add_query_arg( [ 'action' => self::AUTH_ACTION, @@ -427,6 +433,11 @@ public static function send_email( $user, $redirect_to = '', $use_otp = true ) { 'template' => '*MAGIC_LINK_URL*', 'value' => $url, ], + [ + 'template' => '*SET_PASSWORD_LINK*', + 'value' => Emails::get_password_reset_url( $user, $key ), + ], + ]; if ( $use_otp && ! empty( $token_data['otp'] ) ) { $email_type = 'OTP_AUTH'; diff --git a/includes/reader-activation/class-reader-activation-emails.php b/includes/reader-activation/class-reader-activation-emails.php index 37330ab27a..8653b36c86 100644 --- a/includes/reader-activation/class-reader-activation-emails.php +++ b/includes/reader-activation/class-reader-activation-emails.php @@ -106,6 +106,10 @@ public static function add_email_configs( $configs ) { 'label' => __( 'the login link', 'newspack' ), 'template' => '*MAGIC_LINK_URL*', ], + [ + 'label' => __( 'the password reset link', 'newspack' ), + 'template' => '*SET_PASSWORD_LINK*', + ], ] ), ]; diff --git a/includes/templates/reader-activation-emails/otp.php b/includes/templates/reader-activation-emails/otp.php index d19d8cd038..0fb9fabe2d 100644 --- a/includes/templates/reader-activation-emails/otp.php +++ b/includes/templates/reader-activation-emails/otp.php @@ -18,13 +18,13 @@ [ 'block_markup' => $social_links, - 'html_markup' => $social_links_html + 'html_markup' => $social_links_html ] = newspack_get_social_markup( $primary_text_color ); $post_content = // Main body. - ' - +
+

' . __( 'If you did not request this code, please ignore this email.', 'newspack-plugin' ) . '

+
+
+

' . __( 'Frequently Asked Questions', 'newspack' ) . '

+
+

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

-

' . __( 'If you did not request this code, please ignore this email.', 'newspack-plugin' ) . '

+

' . __( 'Can I still create a password?', 'newspack' ) . '
' . sprintf( /* Translators: 1: opening HTML anchor tag 2: closing HTML anchor tag */ __( 'Yes. For security reasons, we recommend signing in with Google or using a one-time code sent to your email, but you can set a password if you prefer. %1$sClick here%2$s to create a password.', 'newspack' ), '', '' ) . '

' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; From 731eed28ba5070a5802f275152b1b7679348244b Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 19 Apr 2024 08:57:30 -0700 Subject: [PATCH 087/243] fix: add baseline line height --- assets/newspack-ui/scss/elements/_typography.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/newspack-ui/scss/elements/_typography.scss b/assets/newspack-ui/scss/elements/_typography.scss index 8aeefc0d89..ec435e9b84 100644 --- a/assets/newspack-ui/scss/elements/_typography.scss +++ b/assets/newspack-ui/scss/elements/_typography.scss @@ -1,6 +1,7 @@ .newspack-ui { font-family: var( --newspack-ui-font-family ); font-size: var( --newspack-ui-font-size-s ); + line-height: var( --newspack-ui-line-height-s ); -webkit-font-smoothing: antialiased; p { From 75bd158d86d97715ca18275c25ca775b8525342a Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 19 Apr 2024 09:08:18 -0700 Subject: [PATCH 088/243] fix: add blanket fixed layout to tables for cell width consistency --- assets/newspack-ui/scss/elements/_tables.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/newspack-ui/scss/elements/_tables.scss b/assets/newspack-ui/scss/elements/_tables.scss index 316040495c..d4d59bedb9 100644 --- a/assets/newspack-ui/scss/elements/_tables.scss +++ b/assets/newspack-ui/scss/elements/_tables.scss @@ -4,6 +4,7 @@ font-size: var( --newspack-ui-font-size-xs ); // Prevent relative font size line-height: var( --newspack-ui-line-height-xs ); margin: calc( var( --newspack-ui-spacer-base ) / -2 ) 0; // Offset cell padding. + table-layout: fixed; th, td { background: transparent; From 9e7bdd4d0e1cccdb9ba4873022e6b52fd9e768bf Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 19 Apr 2024 11:54:18 -0700 Subject: [PATCH 089/243] feat: update icon button, update button classes, fix helper text --- assets/newspack-ui/scss/_modals.scss | 17 ++-------- .../scss/elements/forms/_buttons.scss | 2 +- .../scss/elements/forms/_index.scss | 6 +++- includes/class-newspack-ui.php | 32 +++++++++---------- .../class-reader-activation.php | 8 ++--- 5 files changed, 28 insertions(+), 37 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 55345784a1..48b66c1ec5 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -132,7 +132,7 @@ display: flex; justify-content: space-between; position: sticky; - top: 0; + top: 0; h2 { font-family: var( --newspack-ui-font-family ); @@ -143,20 +143,7 @@ } &__close { - margin: -2px -5px 0 0; // Offsets a padding in the SVG. - padding: 0 0 0 var( --newspack-ui-spacer-base ); - background: transparent; - color: var( --newspack-ui-color-neutral-90 ); - cursor: pointer; - - &:focus, - &:hover { - background: transparent; - color: var( --newspack-ui-color-neutral-70 ); - } - svg { - display: block; - } + margin: -6px -6px -6px 0; // Accounts for the header padding. TODO: Can this be improved to work w/variables? } &__content { diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index 2dadcbee04..665f313b84 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -138,7 +138,7 @@ // Icon-only &--icon { display: grid; - height: var( --newspack-ui-spacer-7 ); // This is the XS size, we will need S, and M + height: var( --newspack-ui-spacer-7 ); // TODO: This is the XS size, we will need S, and M padding: 0; place-items: center; width: var( --newspack-ui-spacer-7 ); diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index e2c837be01..1f2b627a73 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -31,12 +31,16 @@ } // Container for input description. - &__field-description { + &__helper-text { color: var( --newspack-ui-color-neutral-60 ); display: block; font-size: var( --newspack-ui-font-size-xs ); line-height: var( --newspack-ui-line-height-s ); margin: var( --newspack-ui-spacer-base ) 0 var( --newspack-ui-spacer-5 ); + + label & { + margin: 0; + } } // Form response inline error text. diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 68c676157f..48a88b4ba2 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -173,7 +173,7 @@ public static function return_demo_content() { The Weekly
- Friday roundup of the most relevant stories. + Friday roundup of the most relevant stories.
@@ -181,7 +181,7 @@ public static function return_demo_content() { The Weekly
- Friday roundup of the most relevant stories. + Friday roundup of the most relevant stories.

@@ -189,7 +189,7 @@ public static function return_demo_content() { The Weekly
- Friday roundup of the most relevant stories. + Friday roundup of the most relevant stories.
@@ -197,7 +197,7 @@ public static function return_demo_content() { The Weekly
- Friday roundup of the most relevant stories. + Friday roundup of the most relevant stories.
@@ -341,7 +341,7 @@ public static function return_demo_content() {

This is a header

- - - - - - - + + + + + + + - - + +
-

+

-

' . __( 'If you did not request this code, please ignore this email.', 'newspack-plugin' ) . '

-
+

' . __( 'You can also copy and paste this link in your browser:', 'newspack-plugin' ) . '
*MAGIC_LINK_URL*

+

+
-

' . __( 'Frequently Asked Questions', 'newspack' ) . '

+

' . __( 'Frequently Asked Questions', 'newspack' ) . '

-

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

+

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

-

' . __( 'Can I still create a password?', 'newspack' ) . '
' . sprintf( /* Translators: 1: opening HTML anchor tag 2: closing HTML anchor tag */ __( 'Yes. For security reasons, we recommend signing in with Google or using a one-time code sent to your email, but you can set a password if you prefer. %1$sClick here%2$s to create a password.', 'newspack' ), '', '' ) . '

+

' . __( 'Can I still create a password?', 'newspack' ) . '
' . sprintf( /* Translators: 1: opening HTML anchor tag 2: closing HTML anchor tag */ __( 'Yes. For security reasons, we recommend signing in with Google or using a one-time code sent to your email, but you can set a password if you prefer. %1$sClick here%2$s to create a password.', 'newspack' ), '', '' ) . '

' . $social_links_html . '
diff --git a/includes/templates/reader-activation-emails/password-reset.php b/includes/templates/reader-activation-emails/password-reset.php index 0738cbeb0a..824f78d36e 100644 --- a/includes/templates/reader-activation-emails/password-reset.php +++ b/includes/templates/reader-activation-emails/password-reset.php @@ -1,170 +1,264 @@ $primary_color, + 'primary_text_color' => $primary_text_color, +] = newspack_get_theme_colors(); + +[ + 'block_markup' => $social_links, + 'html_markup' => $social_links_html +] = newspack_get_social_markup( $primary_text_color ); + +$post_content = + // Main body. + ' + + ' . + + // Footer. + ' + + '; + +$email_html = ' + + + + ' . __( 'Reset password', 'newspack-plugin' ) . ' + + + + + + + + + + + + + + +
+
+
+
+
acof-flag
+
+

' . __( 'Reset password', 'newspack-plugin' ) . '

+
+

' . __( 'You have just requested a password reset for your account associated with this email address.', 'newspack-plugin' ) . '

+ +
+

' . sprintf( /* Translators: 1: Opening HTML anchor tag containing Newspack support link. 2: Closing HTML anchor tag. */ __( 'If you continue to have issues signing in, please %1$scontact us%2$s.', 'newspack-plugin' ), '', '' ) . '

+
+
+
' . $social_links_html . '
+
+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to reset your password to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+
+ + '; + return array( - 'post_title' => __( 'Set a new password', 'newspack' ), - 'post_content' => ' - - -

' . __( 'Set a new password', 'newspack' ) . '

- - - -

' . __( 'Set a new password for your account by clicking this button:', 'newspack' ) . '

- - - - - - - -

' . __( 'Or copy and paste the link in your browser:', 'newspack' ) . ' *PASSWORD_RESET_LINK*

- ', - 'email_html' => 'Set a new password

' . __( 'Set a new password', 'newspack' ) . '

' . __( 'Set a new password for your account by clicking this button:', 'newspack' ) . '

' . __( 'Or copy and paste the link in your browser:', 'newspack' ) . ' *PASSWORD_RESET_LINK*

', + 'post_title' => __( 'Reset password', 'newspack-plugin' ), + 'post_content' => $post_content, + 'email_html' => $email_html, ); diff --git a/includes/templates/reader-activation-emails/verification.php b/includes/templates/reader-activation-emails/verification.php index 01720d4e83..ef013f971f 100644 --- a/includes/templates/reader-activation-emails/verification.php +++ b/includes/templates/reader-activation-emails/verification.php @@ -1,174 +1,265 @@ $primary_color, + 'primary_text_color' => $primary_text_color, +] = newspack_get_theme_colors(); + +[ + 'block_markup' => $social_links, + 'html_markup' => $social_links_html +] = newspack_get_social_markup( $primary_text_color ); + +$post_content = + // Main body. + ' + + ' . + + // Footer. + ' + + + '; + +$email_html = ' + + + + ' . __( 'Verify your email', 'newspack-plugin' ) . ' + + + + + + + + + + + + + + +
+
+
+
acof-flag
+
+

' . __( 'Verify your email', 'newspack-plugin' ) . '

+
+

' . sprintf( /* Translators: s: The site name. */ __( 'Thanks for creating an account with %s! Click the button below to verify the email address for your account.', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+
+ + + +
+
+
' . $social_links_html . '
+
+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you have registered on %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+
+ + '; + return array( - 'post_title' => __( 'Your verification link', 'newspack-plugin' ), - 'post_content' => ' - - -

' . __( 'Hi there!', 'newspack-plugin' ) . '

- - - -

' . __( 'To manage your account, please verify your email address by clicking the link below:', 'newspack-plugin' ) . '

- - - - - - - -

' . __( 'Or copy and paste the link in your browser:', 'newspack-plugin' ) . ' *VERIFICATION_URL*

- - - -

' . __( 'Once verified, you\'ll be able to edit your profile, set a password for easier access, and manage your newsletter subscriptions and billing information.', 'newspack-plugin' ) . '

- ', - 'email_html' => 'Your verification link

' . __( 'Hi there!', 'newspack-plugin' ) . '

' . __( 'To manage your account, please verify your email address by clicking the link below:', 'newspack-plugin' ) . '

' . __( 'Or copy and paste the link in your browser:', 'newspack-plugin' ) . ' *VERIFICATION_URL*

' . __( 'Once verified, you\'ll be able to edit your profile, set a password for easier access, and manage your newsletter subscriptions and billing information.', 'newspack-plugin' ) . '

', + 'post_title' => __( 'Verify your email', 'newspack-plugin' ), + 'post_content' => $post_content, + 'email_html' => $email_html, ); diff --git a/includes/templates/reader-revenue-emails/cancellation.php b/includes/templates/reader-revenue-emails/cancellation.php index a90d3632f2..50ea17ba84 100644 --- a/includes/templates/reader-revenue-emails/cancellation.php +++ b/includes/templates/reader-revenue-emails/cancellation.php @@ -1,350 +1,258 @@ -

*CANCELLATION_TITLE*

+namespace Newspack; + +// phpcs:disable WordPressVIPMinimum.Security.Mustache.OutputNotation + +[ + 'primary_color' => $primary_color, + 'primary_text_color' => $primary_text_color, +] = newspack_get_theme_colors(); + +[ + 'block_markup' => $social_links, + 'html_markup' => $social_links_html +] = newspack_get_social_markup( $primary_text_color ); + +$post_content = + // Main body. + ' + + ' . + + // Footer. + ' + + '; $email_html = ' - - - - *CANCELLATION_TITLE* - - - - - - - - - - - + + + + + + - - -
- -
- - - - - - -
- -
- - - - - - -
- - - - - - - - -
- -

*CANCELLATION_TITLE*

- -
- -
- -
- - -
- -
- - - - - -
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - -
- -

' . sprintf( /* Translators: 1: the cancellation type (subscription or recurring donation). 2: the site title. */ __( 'This is to confirm the cancellation of your %1$s to %2$s. We\'re sorry to see you go! If you\'d like to restart your %1$s, you can do so by clicking the button below.', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_TITLE*' ) . '

- -
- -
- -
- - -
- -
- - - -
-
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - -
- -

' . sprintf( /* Translators: s: site admin email address. */ __( 'If you have any questions, you can reach us at %s. We appreciate your support!', 'newspack-plugin' ), '*CONTACT_EMAIL*' ) . '

- -
- -
- -
- - -
- -
- -
- -'; + a:active, a:focus, a:hover { + text-decoration: none; + } + a:focus { + outline: thin dotted #000; + } + + /* Button */ + .is-style-outline a { + background: #fff !important; + border: 2px solid !important; + display: block !important; + } + + /* Heading */ + h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0; + } + + h1 { + font-size: 2.44em; + line-height: 1.24; + } + + h2 { + font-size: 1.95em; + line-height: 1.36; + } + + h3 { + font-size: 1.56em; + line-height: 1.44; + } + + h4 { + font-size: 1.25em; + line-height: 1.6; + } + + h5 { + font-size: 1em; + line-height: 1.5em; + } + + h6 { + font-size: 0.8em; + line-height: 1.56; + } + + /* List */ + ul, ol { + margin: 12px 0; + padding: 0; + list-style-position: inside; + } + + /* Quote */ + blockquote, + .wp-block-quote { + background: transparent; + border-left: 0.25em solid; + margin: 0; + padding-left: 24px; + } + blockquote cite, + .wp-block-quote cite { + color: #767676; + } + blockquote p, + .wp-block-quote p { + padding-bottom: 12px; + } + .wp-block-quote.is-style-plain, + .wp-block-quote.is-style-large { + border-left: 0; + padding-left: 0; + } + .wp-block-quote.is-style-large p { + font-size: 24px; + font-style: italic; + line-height: 1.6; + } + + /* Image */ + @media all and (max-width: 590px) { + img { + height: auto !important; + } + } + + /* Social links */ + .social-element img { + border-radius: 0 !important; + } + + /* Has Background */ + .mj-column-has-width .has-background, + .mj-column-per-50 .has-background { + padding: 12px; + } + + /* Mailchimp Footer */ + #canspamBarWrapper { + border: 0 !important; + } + + .has-primary-color { color: ' . esc_attr( $primary_color ) . '; } + + + +
+
+
+
+
acof-flag
+
+

*CANCELLATION_TITLE*

+
+

' . sprintf( /* Translators: 1: the cancellation type (subscription or recurring donation). 2: the site title. */ __( 'This is to confirm the cancellation of your %1$s to %2$s. We\'re sorry to see you go! If you\'d like to restart your %1$s, you can do so by clicking the button below.', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_TITLE*' ) . '

+ +
+

' . sprintf( /* Translators: s: site admin email address. */ __( 'If you have any questions, you can reach us at %s. We appreciate your support.', 'newspack-plugin' ), '*CONTACT_EMAIL*' ) . '

+
+
+
' . $social_links_html . '
+
+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you cancelled your %1$s to %2$s', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_URL*' ) . '

+
+ + '; return array( - 'post_title' => __( 'Subscription Cancelled', 'newspack' ), + 'post_title' => __( 'Subscription cancelled', 'newspack-plugin' ), 'post_content' => $post_content, 'email_html' => $email_html, ); diff --git a/includes/templates/reader-revenue-emails/receipt.php b/includes/templates/reader-revenue-emails/receipt.php index de0a82bfcb..30959d54ba 100644 --- a/includes/templates/reader-revenue-emails/receipt.php +++ b/includes/templates/reader-revenue-emails/receipt.php @@ -1,637 +1,276 @@ __( 'Thank you!', 'newspack' ), - 'post_content' => ' -

Thank You!

- - - -

Your contribution really helps!

- - - -
-
-

Amount paid

- - - -

*AMOUNT*

-
- - - -
-

Date paid

- - - -

*DATE*

-
- - - -
-

Payment method

- - - -

*PAYMENT_METHOD*

-
-
- - - -

If you have any questions, you can reach us at *CONTACT_EMAIL*.

- - - -

Download the receipt at *RECEIPT_URL*.

-', - 'email_html' => ' - - - - Thank you! - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - -
- -

Thank You!

- -
- -
- -
- - -
- -
- - - - - -
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - -
- -

Your contribution really helps!

- -
- -
- -
- - -
- -
- - - - - -
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - - - - - -
- -

Amount paid

- -
- -

*AMOUNT*

- -
- -
- -
- - - -
- - - - - - - -
- - - - - - - - - - - - - -
- -

Date paid

- -
- -

*DATE*

- -
- -
- -
- - - -
- - - - - - - -
- - - - - - - - - - - - - -
- -

Payment method

- -
- -

*PAYMENT_METHOD*

+namespace Newspack; + +// phpcs:disable WordPressVIPMinimum.Security.Mustache.OutputNotation + +[ + 'primary_color' => $primary_color, + 'primary_text_color' => $primary_text_color, +] = newspack_get_theme_colors(); + +[ + 'block_markup' => $social_links, + 'html_markup' => $social_links_html +] = newspack_get_social_markup( $primary_text_color ); + +$post_content = + // Main body. + ' + + ' . + + // Footer. + ' + + '; + +$email_html = ' + + + + ' . __( 'Thank you!', 'newspack-plugin' ) . ' + + + + + + + + + + + + + +
+
+
+
+
acof-flag
+
+

' . __( 'Thank you!', 'newspack-plugin' ) . '

+
+

' . sprintf( /* Translators: s: the site title. */ __( 'Thank you for supporting %s. Here is a receipt for your recent transaction:', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+
+

' . __( 'Amount paid', 'newspack' ) . '

*AMOUNT*

+
+

' . __( 'Date paid', 'newspack' ) . '

*DATE*

+
+

' . __( 'Payment method', 'newspack' ) . '

*PAYMENT_METHOD*

+
+

' . sprintf( /* Translators: 1: site admin email address. 2: my account page link. */ __( 'If you have any questions, you can reach us at %1$s. You can download a copy of this receipt at %2$s.', 'newspack-plugin' ), '*CONTACT_EMAIL*', '*RECEIPT_URL*' ) . '

+
+
+
' . $social_links_html . '
+
+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+
+ + '; -
- -
- -
- - -
- -
- - - - - -
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - -
- -

If you have any questions, you can reach us at *CONTACT_EMAIL*.

- -
- -
- -
- - -
- -
- - - - - -
- - - - - - - -
- - -
- - - - - - - -
- - - - - - - - - -
- -

Download the receipt at *RECEIPT_URL*.

- -
- -
- -
- - -
- -
- - - - - -
- - - - ', +return array( + 'post_title' => __( 'Thank you!', 'newspack-plugin' ), + 'post_content' => $post_content, + 'email_html' => $email_html, ); diff --git a/includes/util.php b/includes/util.php index 49e03f27e6..dd211c908a 100644 --- a/includes/util.php +++ b/includes/util.php @@ -544,15 +544,11 @@ function newspack_get_color_contrast( $hex ) { */ function newspack_get_theme_colors() { $default_primary_color = function_exists( 'newspack_get_primary_color' ) ? newspack_get_primary_color() : '#3366ff'; - $default_secondary_color = function_exists( 'newspack_get_secondary_color' ) ? newspack_get_secondary_color() : '#f0f0f0'; $primary_color = get_theme_mod( 'primary_color_hex', $default_primary_color ); - $secondary_color = get_theme_mod( 'secondary_color_hex', $default_secondary_color ); return [ - 'primary_color' => $primary_color, - 'secondary_color' => $secondary_color, - 'primary_text_color' => newspack_get_color_contrast( $primary_color ), - 'secondary_text_color' => newspack_get_color_contrast( $secondary_color ), + 'primary_color' => $primary_color, + 'primary_text_color' => newspack_get_color_contrast( $primary_color ), ]; } @@ -567,7 +563,7 @@ function newspack_get_social_markup( $color = 'white' ) { $cm = Configuration_Managers::configuration_manager_class_for_plugin_slug( 'wordpress_seo' ); $social_urls = []; $markup = [ - 'block_markup' => '', + 'block_markup' => ''; + return $markup; } From 169e784a7720aed3ad303b3102b1942a1a869527 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Thu, 25 Apr 2024 12:09:06 -0700 Subject: [PATCH 092/243] feat: update error state, form labels, checkbox layouts, and demo content --- .../scss/elements/_typography.scss | 1 + .../scss/elements/forms/_index.scss | 40 ++-- .../scss/elements/forms/_labels.scss | 53 ++++- .../scss/elements/woocommerce/_overrides.scss | 62 ++++-- .../newspack-ui/scss/variables/_colors.scss | 1 + includes/class-newspack-ui.php | 191 ++++++++++++------ .../class-reader-activation.php | 4 +- 7 files changed, 239 insertions(+), 113 deletions(-) diff --git a/assets/newspack-ui/scss/elements/_typography.scss b/assets/newspack-ui/scss/elements/_typography.scss index ec435e9b84..ee5825271f 100644 --- a/assets/newspack-ui/scss/elements/_typography.scss +++ b/assets/newspack-ui/scss/elements/_typography.scss @@ -1,4 +1,5 @@ .newspack-ui { + color: var( --newspack-ui-color-neutral-90 ); font-family: var( --newspack-ui-font-family ); font-size: var( --newspack-ui-font-size-s ); line-height: var( --newspack-ui-line-height-s ); diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index 1f2b627a73..a864f1fc1f 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -30,31 +30,41 @@ } } - // Container for input description. - &__helper-text { + // Form inline text - helper and error. + &__helper-text, + &__inline-error { color: var( --newspack-ui-color-neutral-60 ); display: block; font-size: var( --newspack-ui-font-size-xs ); - line-height: var( --newspack-ui-line-height-s ); - margin: var( --newspack-ui-spacer-base ) 0 var( --newspack-ui-spacer-5 ); + font-weight: normal; + line-height: var( --newspack-ui-line-height-xs ); + margin: var( --newspack-ui-spacer-base ) 0 0; + a { + text-decoration: underline; + } - label & { - margin: 0; + & + & { + margin-top: 0; } - } - // Form response inline error text. - &__inline-error, - &__inline-info { - font-size: var( --newspack-ui-font-size-xs ); - line-height: var( --newspack-ui-line-height-s ); - margin: var( --newspack-ui-spacer-base ) 0 var( --newspack-ui-spacer-5 ); - a { - text-decoration: underline; + label & { + margin: 0; } } &__inline-error { color: var( --newspack-ui-color-error-50 ); } + + // Error class to apply to specific fields. + &__error, + [data-form-status="400"] { // Attribute added to sign-up modal form on failure. + --newspack-ui-color-input-border: var( --newspack-ui-color-error-50 ); + --newspack-ui-color-input-border-focus: var( --newspack-ui-color-error-50 ); + --newspack-ui-label-color: var( --newspack-ui-color-error-50 ); + + .newspack-ui__label-optional { + color: inherit; + } + } } diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss index 20c05753d0..29c62611df 100644 --- a/assets/newspack-ui/scss/elements/forms/_labels.scss +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -1,6 +1,6 @@ .newspack-ui { - // TODO: In the current My Account mockups, these are 16px. label { + color: var( --newspack-ui-label-color ); display: block; font-family: var( --newspack-ui-font-family); font-size: var( --newspack-ui-font-size-s ) !important; // !important to override Newspack Theme. @@ -11,13 +11,20 @@ // For labels containing radio, checkbox inputs: &:has( input[type='checkbox'] ), &:has( input[type='radio'] ) { - align-items: center; - display: flex; - gap: var( --newspack-ui-spacer-2 ); + display: grid; + gap: 0 var( --newspack-ui-spacer-base ); + grid-template-columns: var( --newspack-ui-spacer-4 ) 1fr; + + > *:not( input ) { + grid-column: 2 / span 1; + } + + input { + margin-top: 0.125em; // TODO: improve the way alignment is being achieved here. + } // For creating a bordered 'list' of radio, checkbox inputs: - &.newspack-ui__input-list { - align-items: flex-start; + &.newspack-ui__input-card { border: 1px solid var( --newspack-ui-color-border ); border-radius: var( --newspack-ui-border-radius-m ); cursor: pointer; @@ -31,10 +38,42 @@ border-color: var( --newspack-ui-color-neutral-90 ); } - + .newspack-ui__input-list { + + .newspack-ui__input-card { margin-top: calc( var( --newspack-ui-spacer-2 ) * -1 ); } } + + // 'Selected' label + &:has( .newspack_ui__input-card__selected ) { + grid-template-columns: var( --newspack-ui-spacer-4 ) 1fr min-content; + } + + .newspack_ui__input-card__selected { + align-self: start; + background: var( --newspack-ui-color-neutral-90 ); + border-radius: var( --newspack-ui-border-radius-xs ); + color: var( --newspack-ui-color-neutral-0 ); + font-size: var( --newspack-ui-font-size-xs ); + font-weight: 600; + grid-column-start: 3; + grid-row-start: 1; + line-height: var( --newspack-ui-line-height-xs ); + padding: 2px 6px; // TODO: replace with variables; they only go down to 8px, rethink? + text-transform: uppercase; + } + } + } + + &__label-optional { + color: var( --newspack-ui-color-neutral-60 ); + font-weight: 400; + } + + &__required { + color: var( --newspack-ui-color-error-50 ); + + &[title] { + text-decoration: none; } } } \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index a35c0fde7f..b45766e9e4 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -10,7 +10,7 @@ } } - .newspack-ui__input-list { + .newspack-ui__input-card { label { display: block; } @@ -85,6 +85,33 @@ } } } + + // If the only payment option, we're hiding the radio selection so we don't need a grid. + &:first-child:last-child .newspack-ui__input-card { + grid-template-columns: none; + gap: 0; + } + } + + // Stripe inputs + .wc-credit-card-form { + .form-row-wide { + margin-bottom: var( --newspack-ui-spacer-base ); + } + .wc-stripe-elements-field, + .wc-stripe-iban-element-field { + border: 1px solid var( --newspack-ui-color-input-border ); + border-radius: var( --newspack-ui-border-radius-m ); + display: block; + font-family: var( --newspack-ui-font-family); + font-size: var( --newspack-ui-font-size-s ); + line-height: var( --newspack-ui-line-height-l ); + padding: calc( var( --newspack-ui-spacer-2 ) - 1px ) calc( var( --newspack-ui-spacer-3 ) - 1px ); + } + } + + .wc_payment_methods label[for="payment_method_stripe"].newspack-ui__input-card { + padding: var( --newspack-ui-spacer-5 ) !important; } // Override billing details spacing. @@ -148,32 +175,25 @@ } } - // Stripe inputs - .wc-credit-card-form { - .form-row-wide { - margin-bottom: var( --newspack-ui-spacer-base ); - } - .wc-stripe-elements-field, - .wc-stripe-iban-element-field { - border: 1px solid var( --newspack-ui-color-input-border ); - border-radius: var( --newspack-ui-border-radius-m ); - display: block; - font-family: var( --newspack-ui-font-family); - font-size: var( --newspack-ui-font-size-s ); - line-height: var( --newspack-ui-line-height-l ); - padding: calc( var( --newspack-ui-spacer-2 ) - 1px ) calc( var( --newspack-ui-spacer-3 ) - 1px ); - } - } - - .wc_payment_methods label[for="payment_method_stripe"].newspack-ui__input-list { - padding: var( --newspack-ui-spacer-5 ) !important; + // Required fields. + .woocommerce form .form-row .required { + color: var( --newspack-ui-color-error-50 ); } // Errors .woocommerce-invalid { input, - textarea { + textarea, + .select2-container--default .select2-selection--single { border-color: var( --newspack-ui-color-error-50 ); + + &:focus { + outline-color: var( --newspack-ui-color-error-50 ); + } + } + + label { + color: var( --newspack-ui-color-error-50 ); } } } diff --git a/assets/newspack-ui/scss/variables/_colors.scss b/assets/newspack-ui/scss/variables/_colors.scss index c2f2307258..81a204d92c 100644 --- a/assets/newspack-ui/scss/variables/_colors.scss +++ b/assets/newspack-ui/scss/variables/_colors.scss @@ -74,6 +74,7 @@ --newspack-ui-color-input-border-focus: var( --newspack-ui-color-neutral-90 ); --newspack-ui-color-input-border-disabled: var( --newspack-ui-color-neutral-40 ); --newspack-ui-color-input-background-disabled: var( --newspack-ui-color-neutral-10 ); + --newspack-ui-label-color: var( --newspack-ui-color-neutral-90 ); // Alternatives for when prefers-contrast is set to 'more': @media ( prefers-contrast: more ) { diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 48a88b4ba2..dad1ee6362 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -62,18 +62,38 @@ public static function return_demo_content() { ob_start(); ?>
-

Temporary Razzak Component Demo

+

Component Demo

+ + + +
+ +

Typography

-

X-Large text

-

Large text

-

Medium text

-

Small text (default)

-

X-Small text

2X-Small text

+

X-Small text

+

Small text (default)

+

Medium text

+

Large text

+

X-Large text

+

2X-Large text

+

3X-Large text

+

4X-Large text

+

5X-Large text

+

6X-Large text


-

Boxes

+

Boxes

Default box style

@@ -131,7 +151,7 @@ public static function return_demo_content() {
-

Form elements

+

Form elements

@@ -139,71 +159,117 @@ public static function return_demo_content() {

- +

-
-

- -

+

+ + + Some helper text. +

+ +

+ + + Some helper text. + An error message. +

+ +

+ +

+ +

+ +

+ +

+ +

-

- -

+

+ +

-

- -

+

+ +

+
-

Checkbox/Radio Lists

-

-

Sign in by entering the code sent to email@address.com, or by clicking the magic link in the email.

+

Sign in by entering the code sent to email@address.com, or by clicking the magic link in the email.

@@ -599,10 +599,10 @@ public static function return_demo_content() { If you don't set a password, you can always log in with a magic link or one-time code sent to your email.

- - - + + +
From 8c1a9b10d2a1d3ccb79d34a1f7f1bc5994edaf31 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Thu, 25 Apr 2024 16:26:24 -0700 Subject: [PATCH 097/243] feat: update badge styles --- .../scss/elements/forms/_labels.scss | 4 +-- .../scss/elements/misc/_badge.scss | 35 +++++++++++++++++-- includes/class-newspack-ui.php | 9 +++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss index f1b3524455..651dc6a946 100644 --- a/assets/newspack-ui/scss/elements/forms/_labels.scss +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -44,11 +44,11 @@ } // 'Selected' badge - &:has( .newspack_ui__badge ) { + &:has( .newspack-ui__badge ) { grid-template-columns: var( --newspack-ui-spacer-4 ) 1fr min-content; } - .newspack_ui__badge { + .newspack-ui__badge { align-self: start; grid-column-start: 3; grid-row-start: 1; diff --git a/assets/newspack-ui/scss/elements/misc/_badge.scss b/assets/newspack-ui/scss/elements/misc/_badge.scss index 1c81377a3a..bbf9a150f3 100644 --- a/assets/newspack-ui/scss/elements/misc/_badge.scss +++ b/assets/newspack-ui/scss/elements/misc/_badge.scss @@ -1,7 +1,5 @@ -.newspack_ui__badge { - background: var( --newspack-ui-color-neutral-90 ); +.newspack-ui__badge { border-radius: var( --newspack-ui-border-radius-xs ); - color: var( --newspack-ui-color-neutral-0 ); display: inline-grid; font-size: var( --newspack-ui-font-size-xs ); font-weight: 600; @@ -9,4 +7,35 @@ padding: 2px 6px; // TODO: replace with variables; they only go down to 8px, perhaps they need to be rethought? place-items: center; text-transform: uppercase; + + &--primary { + background: var( --newspack-ui-color-neutral-90 ); + color: var( --newspack-ui-color-neutral-0 ); + } + + &--secondary { + background: var( --newspack-ui-color-neutral-10 ); + color: var( --newspack-ui-color-neutral-90 ); + } + + &--outline { + background: var( --newspack-ui-color-neutral-0 ); + border: 1px solid var( --newspack-ui-color-neutral-30 ); + color: var( --newspack-ui-color-neutral-60 ); + } + + &--success { + background: var( --newspack-ui-color-success-0 ); + color: var( --newspack-ui-color-neutral-90 ); + } + + &--error { + background: var( --newspack-ui-color-error-0 ); + color: var( --newspack-ui-color-neutral-90 ); + } + + &--warning { + background: var( --newspack-ui-color-warning-0 ); + color: var( --newspack-ui-color-neutral-90 ); + } } \ No newline at end of file diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index d2bf62012d..e72bfa65cd 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -257,7 +257,7 @@ public static function return_demo_content() { @@ -314,7 +314,12 @@ public static function return_demo_content() {

Badges (more examples TK)

- Badge
+ Badge
+ Badge
+ Badge
+ Badge
+ Badge
+ Badge

From 381b78520006237f8ec29a1104db627f2a0145ac Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Fri, 26 Apr 2024 11:45:59 +0100 Subject: [PATCH 098/243] feat: add "default" style to badge and fix outline --- assets/newspack-ui/scss/elements/misc/_badge.scss | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/assets/newspack-ui/scss/elements/misc/_badge.scss b/assets/newspack-ui/scss/elements/misc/_badge.scss index bbf9a150f3..1a44cee701 100644 --- a/assets/newspack-ui/scss/elements/misc/_badge.scss +++ b/assets/newspack-ui/scss/elements/misc/_badge.scss @@ -1,5 +1,7 @@ .newspack-ui__badge { + background: var( --newspack-ui-color-neutral-0 ); border-radius: var( --newspack-ui-border-radius-xs ); + color: var( --newspack-ui-color-neutral-90 ); display: inline-grid; font-size: var( --newspack-ui-font-size-xs ); font-weight: 600; @@ -15,27 +17,23 @@ &--secondary { background: var( --newspack-ui-color-neutral-10 ); - color: var( --newspack-ui-color-neutral-90 ); } &--outline { - background: var( --newspack-ui-color-neutral-0 ); - border: 1px solid var( --newspack-ui-color-neutral-30 ); color: var( --newspack-ui-color-neutral-60 ); + outline: 1px solid var( --newspack-ui-color-neutral-30 ); + outline-offset: -1px; } &--success { background: var( --newspack-ui-color-success-0 ); - color: var( --newspack-ui-color-neutral-90 ); } &--error { background: var( --newspack-ui-color-error-0 ); - color: var( --newspack-ui-color-neutral-90 ); } &--warning { background: var( --newspack-ui-color-warning-0 ); - color: var( --newspack-ui-color-neutral-90 ); } } \ No newline at end of file From fb5d4c55d0b8a23b6c3d61d907651d43039856a2 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Fri, 26 Apr 2024 11:58:52 +0100 Subject: [PATCH 099/243] fix: text gray --- assets/newspack-ui/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/newspack-ui/style.scss b/assets/newspack-ui/style.scss index 349fa8a78a..b2954b137f 100644 --- a/assets/newspack-ui/style.scss +++ b/assets/newspack-ui/style.scss @@ -6,7 +6,7 @@ // Need better spot for this &__color-text-gray { - color: var( --newspack-ui-color-neutral-70 ); + color: var( --newspack-ui-color-neutral-60 ); } // Overrides for theme styles -- to move to theme? From 55136c2fc0d0ff304f64c47550b89befdf241f75 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Wed, 8 May 2024 13:54:06 -0700 Subject: [PATCH 100/243] feat: adjust some spacing, font styles --- .../scss/elements/forms/_buttons.scss | 11 ++++- .../scss/elements/forms/_index.scss | 2 +- .../scss/elements/forms/_labels.scss | 4 +- .../scss/elements/misc/_badge.scss | 1 + .../scss/elements/woocommerce/_overrides.scss | 45 +++++++++++++++++-- includes/class-newspack-ui.php | 18 ++++---- 6 files changed, 63 insertions(+), 18 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index 665f313b84..09bbf67877 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -2,8 +2,10 @@ // TODO: define some kind of size hierachy for buttons eg. small, medium, large. &__button { align-items: center; + background: var( --newspack-ui-color-neutral-10 ); border: 0; border-radius: var( --newspack-ui-border-radius-m ); + color: var( --newspack-ui-color-neutral-90 ); display: inline-flex; font-family: var( --newspack-ui-font-family ); font-size: var( --newspack-ui-font-size-s ); @@ -18,9 +20,14 @@ margin-bottom: var( --newspack-ui-spacer-2 ); } + &:hover { + background: var( --newspack-ui-color-neutral-30 ); + color: var( --newspack-ui-color-neutral-90 ); + } + &:disabled { - background: var( --newspack-ui-color-neutral-10 ) !important; - color: var( --newspack-ui-color-neutral-70 ) !important; + background: var( --newspack-ui-color-neutral-5 ) !important; + color: var( --newspack-ui-color-neutral-40 ) !important; cursor: default; pointer-events: none; } diff --git a/assets/newspack-ui/scss/elements/forms/_index.scss b/assets/newspack-ui/scss/elements/forms/_index.scss index a864f1fc1f..f36e2d258c 100644 --- a/assets/newspack-ui/scss/elements/forms/_index.scss +++ b/assets/newspack-ui/scss/elements/forms/_index.scss @@ -57,7 +57,7 @@ } // Error class to apply to specific fields. - &__error, + &__field-error, [data-form-status="400"] { // Attribute added to sign-up modal form on failure. --newspack-ui-color-input-border: var( --newspack-ui-color-error-50 ); --newspack-ui-color-input-border-focus: var( --newspack-ui-color-error-50 ); diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss index 651dc6a946..3cfbb7befe 100644 --- a/assets/newspack-ui/scss/elements/forms/_labels.scss +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -12,7 +12,7 @@ &:has( input[type='checkbox'] ), &:has( input[type='radio'] ) { display: grid; - gap: 0 var( --newspack-ui-spacer-base ); + gap: 0 var( --newspack-ui-spacer-3 ); grid-template-columns: var( --newspack-ui-spacer-4 ) 1fr; > *:not( input ) { @@ -33,7 +33,7 @@ padding: var( --newspack-ui-spacer-3 ); transition: background-color 125ms ease-in-out, border-color 125ms ease-in-out; - &:has( input:checked ) { + &:has( > input:checked ) { background: var( --newspack-ui-color-neutral-5 ); border-color: var( --newspack-ui-color-neutral-90 ); } diff --git a/assets/newspack-ui/scss/elements/misc/_badge.scss b/assets/newspack-ui/scss/elements/misc/_badge.scss index 1a44cee701..33271b0ae3 100644 --- a/assets/newspack-ui/scss/elements/misc/_badge.scss +++ b/assets/newspack-ui/scss/elements/misc/_badge.scss @@ -20,6 +20,7 @@ } &--outline { + background: var( --newspack-ui-color-neutral-0 ); color: var( --newspack-ui-color-neutral-60 ); outline: 1px solid var( --newspack-ui-color-neutral-30 ); outline-offset: -1px; diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index fbd221f950..5f236e0d94 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -48,16 +48,26 @@ // Override checkout payment method box. .wc_payment_method { + + + .wc_payment_method { + margin-top: calc( var(--newspack-ui-spacer-5) / -2 ); + } + span { font-weight: var( --newspack-ui-font-weight-strong ); } + > label:first-of-type { + margin: unset; + } + .payment_box { background: transparent; font-weight: normal; padding: 0; p { + color: var( --newspack-ui-color-neutral-60 ); font-size: var(--newspack-ui-font-size-xs); } @@ -72,7 +82,8 @@ } fieldset { - margin-bottom: var(--newspack-ui-spacer-2); + margin: 0 0 var(--newspack-ui-spacer-2); + padding: 0 !important; // To override inline styles. &:last-child { margin-bottom: 0; @@ -99,10 +110,19 @@ } } + // Override a style coming from the theme to hide the radio -- we need this when there's more than one option. + input.input-radio[name="payment_method"] { + display: inherit; + } + // If the only payment option, we're hiding the radio selection so we don't need a grid. &:first-child:last-child .newspack-ui__input-card { grid-template-columns: none; gap: 0; + + input.input-radio[name="payment_method"] { + display: none; + } } } @@ -142,8 +162,17 @@ } } - .wc_payment_methods label[for="payment_method_stripe"].newspack-ui__input-card { - padding: var( --newspack-ui-spacer-5 ) !important; + .wc_payment_methods label[for="payment_method_stripe"] { + &.newspack-ui__input-card { + padding: var( --newspack-ui-spacer-3 ) !important; + } + } + + // Woo Payments inputs + #wcpay-upe-element, + .wcpay-upe-element { + margin: var(--newspack-ui-spacer-5) 0; + padding: 0; } // Override billing details spacing. @@ -228,4 +257,14 @@ color: var( --newspack-ui-color-error-50 ); } } + + // Buttons - adjust spacing + #place-order { + margin-bottom: 0; + } + + // stylelint-disable-next-line selector-id-pattern + #checkout_back { + margin-top: 0; + } } diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index e72bfa65cd..c4bb743f58 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -169,9 +169,9 @@ public static function return_demo_content() { Some helper text.

-

- - +

+ + Some helper text. An error message.

@@ -191,8 +191,8 @@ public static function return_demo_content() {

-

-

+

-

-

+ @@ -313,7 +313,7 @@ public static function return_demo_content() {


-

Badges (more examples TK)

+

Badges

Badge
Badge
Badge
@@ -326,7 +326,6 @@ public static function return_demo_content() {

Buttons

newspack-ui__button--primary, --branded, --secondary, --ghost, and --destructive classes for colours/borders, and newspack-ui__button--wide for being 100% wide

-



@@ -352,7 +351,6 @@ public static function return_demo_content() {

Wide buttons

- From 54fd12e4f81759e4e18908725279782f17eafb7f Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Wed, 8 May 2024 15:03:27 -0700 Subject: [PATCH 101/243] feat: make button styles more specific --- assets/newspack-ui/scss/elements/forms/_buttons.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index 09bbf67877..d190cfb499 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -1,6 +1,6 @@ .newspack-ui { // TODO: define some kind of size hierachy for buttons eg. small, medium, large. - &__button { + .newspack-ui__button { align-items: center; background: var( --newspack-ui-color-neutral-10 ); border: 0; From 0f66bf5bf0cb14697d703e1b5b86e71793441779 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Wed, 8 May 2024 17:48:06 -0700 Subject: [PATCH 102/243] feat: update variation styles --- assets/newspack-ui/scss/_modals.scss | 143 ++++++++++++++------------- 1 file changed, 76 insertions(+), 67 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 48b66c1ec5..01b977ca1b 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -41,74 +41,7 @@ } } } - &__modal-variation { - .newspack-ui { - &__modal { - &__content { - padding: var( --newspack-ui-spacer-5 ); - overflow: auto; - border-radius: var( --newspack-ui-border-radius-m ); - h3 { - font-size: var( --newspack-ui-font-size-s ); - margin: 0; - } - p { - font-size: var( --newspack-ui-font-size-xs ); - } - } - } - - &__options { - list-style: none; - display: flex; - flex-wrap: wrap; - gap: var( --newspack-ui-spacer-3 ); - margin: 0; - padding: 0; - &__item { - border: 1px solid var(--newspack-ui-color-border ); - border-radius: var( --newspack-ui-border-radius-m ); - text-align: center; - flex: 1 1 100%; - @media ( min-width: 600px ) { - flex: 1 1 30%; - max-width: calc( 33.3333% - 10px ); - &:first-child:nth-last-child( 2 ), - &:first-child:nth-last-child( 2 ) ~ li { - flex: 1 1 40%; - max-width: calc( 50% - 10px ); - } - } - .summary { - font-size: var( --newspack-ui-font-size-xs ); - padding: var( --newspack-ui-spacer-2 ); - border-bottom: 1px solid var( --newspack-ui-color-border ); - bdi { - display: block; - font-weight: 600; - font-size: var( --newspack-ui-font-size-xl ); - } - } - .variation { - padding: var( --newspack-ui-spacer-2 ); - font-size: var( --newspack-ui-font-size-xs ); - line-height: 1.5; - border-bottom: 1px solid var(--newspack-ui-color-border ); - font-weight: 600; - } - form { - padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-2 ) 0; - button { - display: block; - width: 100%; - font-size: var( --newspack-ui-font-size-xs ); - } - } - } - } - } - } &__modal { // Modal styles background: var( --newspack-ui-color-body-bg ); @@ -182,4 +115,80 @@ } } } + + &__modal-variation { + .newspack-ui { + &__modal { + &__content { + h3 { + font-size: var( --newspack-ui-font-size-s ); + margin: 0; + } + p { + font-size: var( --newspack-ui-font-size-xs ); + } + } + } + + &__options { + list-style: none; + display: flex; + flex-wrap: wrap; + gap: var( --newspack-ui-spacer-3 ); + margin: var( --newspack-ui-spacer-5 ) 0 0; + padding: 0; + + &__item { + border: 1px solid var(--newspack-ui-color-border ); + border-radius: var( --newspack-ui-border-radius-m ); + display: flex; + flex-direction: column; + flex: 1 1 100%; + text-align: center; + + @media ( min-width: 600px ) { + flex: 1 1 30%; + max-width: calc( 33.3333% - 10px ); + &:first-child:nth-last-child( 2 ), + &:first-child:nth-last-child( 2 ) ~ li { + flex: 1 1 40%; + max-width: calc( 50% - 10px ); + } + } + + .summary { + font-size: var( --newspack-ui-font-size-xs ); + line-height: var( --newspack-ui-line-height-xs ); + padding: var( --newspack-ui-spacer-2 ); + + // Scale up just the primary price for a product, not other fees: + .price > .amount > bdi, + .price > ins > .amount > bdi { + display: block; + font-weight: 600; + font-size: var( --newspack-ui-font-size-xl ); + } + } + + .variation { + margin-top: auto; + padding: var( --newspack-ui-spacer-2 ); + font-size: var( --newspack-ui-font-size-xs ); + line-height: var( --newspack-ui-line-height-xs ); + border-top: 1px solid var(--newspack-ui-color-border ); + font-weight: 600; + } + + form { + border-top: 1px solid var(--newspack-ui-color-border ); + padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-2 ) 0; + button { + display: block; + width: 100%; + } + } + } + } + } + } } From 7be8adb4dbe0a27cd9c57dd4fd41f2b64f23e468 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 10 May 2024 10:00:14 -0700 Subject: [PATCH 103/243] feat: add mixin for media queries --- assets/newspack-ui/scss/_mixins.scss | 22 +++++++++++++++++++ assets/newspack-ui/scss/_modals.scss | 16 +++++--------- .../scss/variables/_breakpoints.scss | 3 +++ assets/newspack-ui/scss/variables/_index.scss | 1 + 4 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 assets/newspack-ui/scss/variables/_breakpoints.scss diff --git a/assets/newspack-ui/scss/_mixins.scss b/assets/newspack-ui/scss/_mixins.scss index 0795945d2a..85be3bd83c 100644 --- a/assets/newspack-ui/scss/_mixins.scss +++ b/assets/newspack-ui/scss/_mixins.scss @@ -1,3 +1,5 @@ +@use 'variables/breakpoints'; + @mixin newspack-ui-elevation($size: 1) { @if $size == 1 { box-shadow: 0 1px 10px rgba( 0, 0, 0, 0.07 ); @@ -6,4 +8,24 @@ } @else if $size == 3 { box-shadow: 0 3px 30px rgba( 0, 0, 0, 0.21 ); } +} + +@mixin media( $res ) { + @if mobile == $res { + @media only screen and ( min-width: breakpoints.$mobile_width ) { + @content; + } + } + + @if tablet == $res { + @media only screen and ( min-width: breakpoints.$tablet_width ) { + @content; + } + } + + @if desktop == $res { + @media only screen and ( min-width: breakpoints.$desktop_width ) { + @content; + } + } } \ No newline at end of file diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 01b977ca1b..61083d1daf 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -118,16 +118,10 @@ &__modal-variation { .newspack-ui { - &__modal { - &__content { - h3 { - font-size: var( --newspack-ui-font-size-s ); - margin: 0; + &__selection { + > *:first-child { + margin-top: 0; } - p { - font-size: var( --newspack-ui-font-size-xs ); - } - } } &__options { @@ -146,7 +140,7 @@ flex: 1 1 100%; text-align: center; - @media ( min-width: 600px ) { + @include mixins.media( mobile ) { flex: 1 1 30%; max-width: calc( 33.3333% - 10px ); &:first-child:nth-last-child( 2 ), @@ -161,7 +155,7 @@ line-height: var( --newspack-ui-line-height-xs ); padding: var( --newspack-ui-spacer-2 ); - // Scale up just the primary price for a product, not other fees: + // Scale up just the primary price for a product, not the other fees: .price > .amount > bdi, .price > ins > .amount > bdi { display: block; diff --git a/assets/newspack-ui/scss/variables/_breakpoints.scss b/assets/newspack-ui/scss/variables/_breakpoints.scss new file mode 100644 index 0000000000..36e3aa0942 --- /dev/null +++ b/assets/newspack-ui/scss/variables/_breakpoints.scss @@ -0,0 +1,3 @@ +$mobile_width: 600px; +$tablet_width: 782px; +$desktop_width: 1168px; \ No newline at end of file diff --git a/assets/newspack-ui/scss/variables/_index.scss b/assets/newspack-ui/scss/variables/_index.scss index 1acd68a9ed..c72449e467 100644 --- a/assets/newspack-ui/scss/variables/_index.scss +++ b/assets/newspack-ui/scss/variables/_index.scss @@ -1,3 +1,4 @@ +@use 'breakpoints'; @use 'colors'; @use 'fonts'; @use 'spacing'; From 007763d443db59025daf3e751a2db7dee6540d40 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Mon, 13 May 2024 16:28:27 -0700 Subject: [PATCH 104/243] feat: fixing some spacing issues --- .../scss/elements/forms/_labels.scss | 3 ++- includes/class-newspack-ui.php | 20 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_labels.scss b/assets/newspack-ui/scss/elements/forms/_labels.scss index 3cfbb7befe..b9192cdf32 100644 --- a/assets/newspack-ui/scss/elements/forms/_labels.scss +++ b/assets/newspack-ui/scss/elements/forms/_labels.scss @@ -12,7 +12,7 @@ &:has( input[type='checkbox'] ), &:has( input[type='radio'] ) { display: grid; - gap: 0 var( --newspack-ui-spacer-3 ); + gap: 0 var( --newspack-ui-spacer-base ); grid-template-columns: var( --newspack-ui-spacer-4 ) 1fr; > *:not( input ) { @@ -29,6 +29,7 @@ border-radius: var( --newspack-ui-border-radius-m ); cursor: pointer; font-weight: normal; + gap: 0 var( --newspack-ui-spacer-3 ); margin-bottom: var( --newspack-ui-spacer-5 ); padding: var( --newspack-ui-spacer-3 ); transition: background-color 125ms ease-in-out, border-color 125ms ease-in-out; diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index c4bb743f58..d0cd609bdc 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -222,13 +222,13 @@ public static function return_demo_content() { @@ -236,19 +236,19 @@ public static function return_demo_content() { @@ -256,14 +256,14 @@ public static function return_demo_content() { @@ -296,7 +296,7 @@ public static function return_demo_content() { - GST 5%) + GST 5% $9.00 @@ -632,7 +632,7 @@ public static function return_demo_content() { @@ -640,7 +640,7 @@ public static function return_demo_content() { From 790b903a0f8650e84c857fbdad048ede16bdfa93 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 14 May 2024 09:52:09 -0700 Subject: [PATCH 105/243] fix: update privacy policy text --- assets/newspack-ui/scss/elements/woocommerce/_overrides.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss index 5f236e0d94..3a4fdf207b 100644 --- a/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss +++ b/assets/newspack-ui/scss/elements/woocommerce/_overrides.scss @@ -258,6 +258,11 @@ } } + // Privacy Policy + .woocommerce-privacy-policy-text { + color: var( --newspack-ui-color-neutral-60 ); + } + // Buttons - adjust spacing #place-order { margin-bottom: 0; From 995fbc5a2ad5516655a9648b5159eaab3a5dd93e Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 14 May 2024 13:56:19 -0700 Subject: [PATCH 106/243] feat: add segment control --- assets/newspack-ui/index.js | 1 + assets/newspack-ui/js/index.js | 1 + .../newspack-ui/js/segmented-control/index.js | 34 ++++++ assets/newspack-ui/js/utils/index.js | 25 ++++ assets/newspack-ui/scss/elements/_index.scss | 1 + .../scss/elements/_segmented-control.scss | 43 +++++++ .../scss/elements/forms/_buttons.scss | 34 +++++- includes/class-newspack-ui.php | 112 ++++++++++++++++-- 8 files changed, 238 insertions(+), 13 deletions(-) create mode 100644 assets/newspack-ui/js/index.js create mode 100644 assets/newspack-ui/js/segmented-control/index.js create mode 100644 assets/newspack-ui/js/utils/index.js create mode 100644 assets/newspack-ui/scss/elements/_segmented-control.scss diff --git a/assets/newspack-ui/index.js b/assets/newspack-ui/index.js index 423b033ce7..72c8d03a0b 100644 --- a/assets/newspack-ui/index.js +++ b/assets/newspack-ui/index.js @@ -1 +1,2 @@ import './style.scss'; +import './js/index.js'; diff --git a/assets/newspack-ui/js/index.js b/assets/newspack-ui/js/index.js new file mode 100644 index 0000000000..1075a5b952 --- /dev/null +++ b/assets/newspack-ui/js/index.js @@ -0,0 +1 @@ +import './segmented-control'; diff --git a/assets/newspack-ui/js/segmented-control/index.js b/assets/newspack-ui/js/segmented-control/index.js new file mode 100644 index 0000000000..ef1d2103de --- /dev/null +++ b/assets/newspack-ui/js/segmented-control/index.js @@ -0,0 +1,34 @@ +import { domReady } from '../utils'; // Global utils. + +domReady( function () { + function segmented_control( element ) { + const header = element.querySelector( '.newspack-ui__segmented-control__tabs' ); + const tab_headers = [ ...header.children ]; + const tab_body = element.querySelector( '.newspack-ui__segmented-control__content' ); + let tab_contents = []; + + if ( null !== tab_body ) { + tab_contents = [ ...tab_body.children ]; + } + + tab_headers.forEach( ( tab, i ) => { + if ( tab_contents.length !== 0 && tab.classList.contains( 'selected' ) ) { + tab_contents[ i ].classList.add( 'selected' ); + } + + tab.addEventListener( 'click', function () { + tab_headers.forEach( t => t.classList.remove( 'selected' ) ); + this.classList.add( 'selected' ); + + if ( tab_contents.length !== 0 ) { + tab_contents.forEach( content => content.classList.remove( 'selected' ) ); + tab_contents[ i ].classList.add( 'selected' ); + } + } ); + } ); + } + + [ ...document.querySelectorAll( '.newspack-ui__segmented-control' ) ].forEach( x => + segmented_control( x ) + ); +} ); diff --git a/assets/newspack-ui/js/utils/index.js b/assets/newspack-ui/js/utils/index.js new file mode 100644 index 0000000000..17c2b92274 --- /dev/null +++ b/assets/newspack-ui/js/utils/index.js @@ -0,0 +1,25 @@ +/** + * Util functions. + */ + +/** + * Specify a function to execute when the DOM is fully loaded. + * + * @see https://github.com/WordPress/gutenberg/blob/trunk/packages/dom-ready/ + * + * @param {Function} callback A function to execute after the DOM is ready. + * @return {void} + */ +export const domReady = callback => { + if ( typeof document === 'undefined' ) { + return; + } + if ( + document.readyState === 'complete' || // DOMContentLoaded + Images/Styles/etc loaded, so we call directly. + document.readyState === 'interactive' // DOMContentLoaded fires at this point, so we call directly. + ) { + return void callback(); + } + // DOMContentLoaded has not fired yet, delay callback until then. + document.addEventListener( 'DOMContentLoaded', callback ); +}; diff --git a/assets/newspack-ui/scss/elements/_index.scss b/assets/newspack-ui/scss/elements/_index.scss index 8135ecc6d4..77410cd29d 100644 --- a/assets/newspack-ui/scss/elements/_index.scss +++ b/assets/newspack-ui/scss/elements/_index.scss @@ -2,6 +2,7 @@ @use 'forms'; @use 'icons'; @use 'misc'; +@use 'segmented-control'; @use 'tables'; @use 'typography'; @use 'woocommerce'; diff --git a/assets/newspack-ui/scss/elements/_segmented-control.scss b/assets/newspack-ui/scss/elements/_segmented-control.scss new file mode 100644 index 0000000000..92057dea6f --- /dev/null +++ b/assets/newspack-ui/scss/elements/_segmented-control.scss @@ -0,0 +1,43 @@ +.newspack-ui { + &__segmented-control { + align-items: center; + display: flex; + gap: var( --newspack-ui-spacer-2 ); + flex-direction: column; + + &:not( :last-child ) { + margin-bottom: var( --newspack-ui-spacer-2 ); + } + + &__tabs { + background: var( --newspack-ui-color-neutral-10 ); + border-radius: var( --newspack-ui-border-radius-m ); + display: flex; + flex-wrap: wrap; + gap: calc( var( --newspack-ui-spacer-base ) / 2 ); + justify-content: center; + padding: calc( var( --newspack-ui-spacer-base ) / 2 ); + + .newspack-ui__button { + background: transparent; + border: 1px solid transparent; + color: var( --newspack-ui-color-neutral-60 ); + margin: 0; + + &.selected { + background: var( --newspack-ui-color-neutral-0 ); + border-color: var( --newspack-ui-color-neutral-30 ); + color: var( --newspack-ui-color-neutral-90 ); + } + } + } + + &__content { + width: 100%; + + > *:not( .selected ) { + display: none; + } + } + } +} \ No newline at end of file diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index 665f313b84..a16609dd9d 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -8,10 +8,11 @@ font-family: var( --newspack-ui-font-family ); font-size: var( --newspack-ui-font-size-s ); font-weight: 600; - gap: var( --newspack-ui-spacer-2 ); + gap: calc( var( --newspack-ui-spacer-base ) / 2 ); justify-content: center; line-height: var( --newspack-ui-line-height-s ); - padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-4 ); + min-height: var( --newspack-ui-spacer-9 ); + padding: var( --newspack-ui-spacer-2 ) var( --newspack-ui-spacer-5 ); transition: background-color 125ms ease-in-out, border-color 125ms ease-in-out, outline 125ms ease-in-out; &:not( :last-child ) { @@ -30,6 +31,26 @@ outline-offset: 1px; } + // Sizes + &--x-small { + border-radius: var( --newspack-ui-border-radius-s ); + font-size: var( --newspack-ui-font-size-xs ); + line-height: var( --newspack-ui-line-height-xs ); + min-height: var( --newspack-ui-spacer-6 ); + padding: calc( var( --newspack-ui-spacer-base ) / 2 ) var( --newspack-ui-spacer-base ); + } + + &--small { + font-size: var( --newspack-ui-font-size-xs ); + line-height: var( --newspack-ui-line-height-xs ); + min-height: var( --newspack-ui-spacer-8 ); + padding: var( --newspack-ui-spacer-base ) var( --newspack-ui-spacer-3 ); + } + + &--medium { + // is the default. + } + // Styles &--primary { background: var( --newspack-ui-color-button-bg ); @@ -139,13 +160,16 @@ &--icon { display: grid; height: var( --newspack-ui-spacer-7 ); // TODO: This is the XS size, we will need S, and M + min-height: unset; padding: 0; place-items: center; width: var( --newspack-ui-spacer-7 ); - svg { - fill: currentcolor; - } + + } + + svg { + fill: currentcolor; } } } diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 48a88b4ba2..afc09058aa 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -35,6 +35,14 @@ public static function enqueue_styles() { [], NEWSPACK_PLUGIN_VERSION ); + + wp_enqueue_script( + 'newspack-ui', + Newspack::plugin_url() . '/dist/newspack-ui.js', + [], + NEWSPACK_PLUGIN_VERSION, + true + ); } /** @@ -269,17 +277,13 @@ public static function return_demo_content() { - - Sign in with Google - + Sign in with Google - - + +
+ +
+
+
+
+
+
+
+
+
+
+ + + + + +
+
+ +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
+

Buttons Icon

Uses the same classes as the newspack-ui__button but we add an extra class to it newspack-ui__button--icon


+

Uses the newspack-ui__button--small and newspack-ui__button--medium CSS classes to get different sizes (x-small is the default).

+ + + + +

Modals

From 905216896b4da3b2390c189f8dcbf7695d48ee1a Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 14 May 2024 15:06:55 -0700 Subject: [PATCH 108/243] feat: add loading styles --- .../scss/elements/forms/_buttons.scss | 33 +++++++++++ includes/class-newspack-ui.php | 57 ++++++++++++------- 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index a57062bf4e..aa5e05f6b5 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -185,5 +185,38 @@ svg { fill: currentcolor; } + + // Loading + &--loading { + position: relative; + + span { + visibility: hidden; + } + + &::before { + animation: button-loading 1s infinite linear; + border: 2px solid; + border-color: currentcolor currentcolor transparent transparent; + border-radius: 50%; + content: ''; + display: block; + height: var( --newspack-ui-spacer-3 ); + position: absolute; + width: var( --newspack-ui-spacer-3 ); + } + } + } +} + +@keyframes button-loading { + 0% { + transform: rotate( 0deg ); + } + 50% { + transform: rotate( 180deg ); + } + 100% { + transform: rotate( 360deg ); } } diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 2b431c0f98..3fc99273ec 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -271,25 +271,28 @@ public static function return_demo_content() {

+ +
+ @@ -339,6 +342,20 @@ public static function return_demo_content() {
+
+ +
+ + + +
+
@@ -489,11 +506,11 @@ public static function return_demo_content() {


@@ -288,11 +288,11 @@ public static function return_demo_content() { @@ -506,11 +506,11 @@ public static function return_demo_content() {
@@ -366,46 +368,48 @@ public static function return_demo_content() {
+
+
- +
-
+
-
-
+
+
-
-
-
+
+
+
@@ -702,6 +706,66 @@ public static function return_demo_content() { +
+
+
+

Change Subscription

+ + +
+ +
+
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+
+
From 96f7cd2fabe5835834bb7ffe1bbd9eb5d1469d0f Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Wed, 15 May 2024 08:56:00 -0700 Subject: [PATCH 111/243] feat: make sales price absolutely positioned --- assets/newspack-ui/scss/_modals.scss | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 61083d1daf..829626e6fe 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -66,6 +66,7 @@ justify-content: space-between; position: sticky; top: 0; + z-index: 10; h2 { font-family: var( --newspack-ui-font-family ); @@ -153,14 +154,24 @@ .summary { font-size: var( --newspack-ui-font-size-xs ); line-height: var( --newspack-ui-line-height-xs ); - padding: var( --newspack-ui-spacer-2 ); - - // Scale up just the primary price for a product, not the other fees: - .price > .amount > bdi, - .price > ins > .amount > bdi { - display: block; - font-weight: 600; - font-size: var( --newspack-ui-font-size-xl ); + padding: var( --newspack-ui-spacer-4 ) var( --newspack-ui-spacer-2 ); + position: relative; + + .price { + // Scale up just the primary price for a product, not the other fees: + > .amount > bdi, + > ins > .amount > bdi { + display: block; + font-weight: 600; + font-size: var( --newspack-ui-font-size-xl ); + } + + del { + position: absolute; + width: 100%; + left: 0; + top: var( --newspack-ui-spacer-base ); + } } } From 4080242c5cd87b434115a870325657ce3455b962 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Wed, 15 May 2024 11:23:53 -0700 Subject: [PATCH 112/243] feat: consolidate Newspack UI SVGs --- includes/class-newspack-ui-icons.php | 99 ++++++++++++++++++++++++ includes/class-newspack-ui.php | 111 ++++++--------------------- includes/class-newspack.php | 1 + 3 files changed, 124 insertions(+), 87 deletions(-) create mode 100644 includes/class-newspack-ui-icons.php diff --git a/includes/class-newspack-ui-icons.php b/includes/class-newspack-ui-icons.php new file mode 100644 index 0000000000..aefaa0c7a8 --- /dev/null +++ b/includes/class-newspack-ui-icons.php @@ -0,0 +1,99 @@ + array( + 'class' => true, + 'aria-hidden' => true, + 'aria-labelledby' => true, + 'role' => true, + 'xmlns' => true, + 'width' => true, + 'height' => true, + 'viewbox' => true, + ), + 'g' => array( + 'fill' => true, + 'fill-rule' => true, + ), + 'title' => array( + 'title' => true, + ), + 'path' => array( + 'd' => true, + 'fill' => true, + ), + 'defs' => true, + 'clipPath' => true, + 'polygon' => array( + 'points' => true, + ), + ); + return $svg_args; + } + + /** + * User Interface icons – svg sources. + * + * @var array + */ + public static $ui_icons = array( + 'check' => + '', + 'close' => + '', + 'comment-author-gravatar' => + ' + + ', + 'error' => + '', + 'google' => + ' + + + + + ', + 'menu' => + '', + ); +} diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 48a88b4ba2..db816655ed 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -88,16 +88,8 @@ public static function return_demo_content() {
- - +

Success box style, plus icon + newspack-ui__box--text-center class. @@ -107,9 +99,7 @@ public static function return_demo_content() {

- +

Warning box style, plus icon + newspack-ui__box--text-center class. @@ -119,9 +109,7 @@ public static function return_demo_content() {

- +

Error box style, plus icon + newspack-ui__box--text-center class. @@ -263,12 +251,7 @@ public static function return_demo_content() {


@@ -343,9 +307,7 @@ public static function return_demo_content() {

This is a header

@@ -368,21 +330,15 @@ public static function return_demo_content() {
@@ -453,9 +407,7 @@ public static function return_demo_content() { @@ -463,9 +415,7 @@ public static function return_demo_content() {
- +

@@ -489,9 +439,7 @@ public static function return_demo_content() { @@ -499,9 +447,7 @@ public static function return_demo_content() {

- +

@@ -541,9 +487,7 @@ public static function return_demo_content() { @@ -582,21 +526,14 @@ public static function return_demo_content() {




@@ -307,7 +307,7 @@ public static function return_demo_content() {

This is a header

@@ -330,7 +330,7 @@ public static function return_demo_content() { @@ -338,7 +338,7 @@ public static function return_demo_content() { @@ -407,7 +407,7 @@ public static function return_demo_content() { @@ -415,7 +415,7 @@ public static function return_demo_content() {
- +

@@ -439,7 +439,7 @@ public static function return_demo_content() { @@ -447,7 +447,7 @@ public static function return_demo_content() {

- +

@@ -487,7 +487,7 @@ public static function return_demo_content() { @@ -526,14 +526,14 @@ public static function return_demo_content() {

@@ -1394,10 +1363,8 @@ public static function render_third_party_auth() { } ?>
From 98e11722e3cf0b4460f24efdbffb60e5d26631dd Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Thu, 16 May 2024 10:49:05 -0700 Subject: [PATCH 114/243] feat: update markup to match component updates --- .../scss/elements/_segmented-control.scss | 9 ++- includes/class-newspack-ui.php | 68 ++++++++----------- 2 files changed, 36 insertions(+), 41 deletions(-) diff --git a/assets/newspack-ui/scss/elements/_segmented-control.scss b/assets/newspack-ui/scss/elements/_segmented-control.scss index 67d60fed1c..974351134f 100644 --- a/assets/newspack-ui/scss/elements/_segmented-control.scss +++ b/assets/newspack-ui/scss/elements/_segmented-control.scss @@ -18,7 +18,10 @@ background: transparent; border: 1px solid transparent; color: var( --newspack-ui-color-neutral-60 ); - margin: 0; + + &:not( :last-child ) { + margin: 0; + } &.selected { background: var( --newspack-ui-color-neutral-0 ); @@ -36,6 +39,10 @@ &:not( .selected ) { display: none; } + + > *:last-child { + margin-bottom: 0 !important; + } } } } \ No newline at end of file diff --git a/includes/class-newspack-ui.php b/includes/class-newspack-ui.php index 22ee4e6321..cfe90922ca 100644 --- a/includes/class-newspack-ui.php +++ b/includes/class-newspack-ui.php @@ -451,35 +451,29 @@ public static function return_demo_content() {
-
-
@@ -802,35 +796,29 @@ public static function return_demo_content() {
-
-
From 4ddeff6a4940d2ca900667f1553846041d48f3a6 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Thu, 16 May 2024 13:41:42 -0700 Subject: [PATCH 115/243] feat: updating line height, spacing --- assets/newspack-ui/scss/_modals.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 150612a8f0..217ad75386 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -159,7 +159,7 @@ .summary { font-size: var( --newspack-ui-font-size-xs ); line-height: var( --newspack-ui-line-height-xs ); - padding: var( --newspack-ui-spacer-4 ) var( --newspack-ui-spacer-2 ); + padding: var( --newspack-ui-spacer-5 ) var( --newspack-ui-spacer-2 ); position: relative; .price { @@ -169,6 +169,7 @@ display: block; font-weight: 600; font-size: var( --newspack-ui-font-size-xl ); + line-height: var( --newspack-ui-line-height-xl ); } del { From 66e3548814bc7555786b81b9983d656fcfb7e583 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Fri, 17 May 2024 11:28:27 +0100 Subject: [PATCH 116/243] fix: correct line-height for h2 and h3 --- assets/newspack-ui/scss/_modals.scss | 31 ++++++++++++++++++++-------- assets/newspack-ui/style.scss | 1 + 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 217ad75386..71509638dd 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -62,6 +62,7 @@ align-items: center; background: var( --newspack-ui-color-body-bg ); border-bottom: 1px solid var( --newspack-ui-color-border ); + color: var( --newspack-ui-color-neutral-90 ); display: flex; justify-content: space-between; position: sticky; @@ -82,6 +83,7 @@ &__content { backface-visibility: visible; + color: var( --newspack-ui-color-neutral-90 ); padding: var( --newspack-ui-spacer-5 ); // Make sure there's enough space above the first button in modals @@ -124,17 +126,27 @@ &__modal-variation { .newspack-ui { + color: red; + &__selection { - > *:first-child { - margin-top: 0; + > *:first-child { + margin-top: 0; + } + + h3 { + margin: 0; + + + p { + margin-top: calc( var( --newspack-ui-spacer-base ) / 2); } + } } &__options { list-style: none; display: flex; flex-wrap: wrap; - gap: var( --newspack-ui-spacer-3 ); + gap: var( --newspack-ui-spacer-2 ); margin: var( --newspack-ui-spacer-5 ) 0 0; padding: 0; @@ -173,21 +185,22 @@ } del { + color: var( --newspack-ui-color-neutral-60 ); + left: 0; position: absolute; + top: calc( var( --newspack-ui-spacer-base ) * 0.75 ); width: 100%; - left: 0; - top: var( --newspack-ui-spacer-base ); } } } .variation { - margin-top: auto; - padding: var( --newspack-ui-spacer-2 ); - font-size: var( --newspack-ui-font-size-xs ); - line-height: var( --newspack-ui-line-height-xs ); border-top: 1px solid var(--newspack-ui-color-border ); + font-size: var( --newspack-ui-font-size-xs ); font-weight: 600; + line-height: var( --newspack-ui-line-height-xs ); + margin-top: auto; + padding: var( --newspack-ui-spacer-2 ); } form { diff --git a/assets/newspack-ui/style.scss b/assets/newspack-ui/style.scss index b2954b137f..15ab32076e 100644 --- a/assets/newspack-ui/style.scss +++ b/assets/newspack-ui/style.scss @@ -13,6 +13,7 @@ h2, h3 { font-size: var( --newspack-ui-font-size-s ); + line-height: var( --newspack-ui-line-height-s ); } a, From 434e9addf874ded03405896789e442e3705036be Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Fri, 17 May 2024 12:04:26 -0700 Subject: [PATCH 117/243] fix: remove text colour style --- assets/newspack-ui/scss/_modals.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/newspack-ui/scss/_modals.scss b/assets/newspack-ui/scss/_modals.scss index 71509638dd..4771833240 100644 --- a/assets/newspack-ui/scss/_modals.scss +++ b/assets/newspack-ui/scss/_modals.scss @@ -126,7 +126,6 @@ &__modal-variation { .newspack-ui { - color: red; &__selection { > *:first-child { From 9558443d06cf8fa50ff235f0d6e2b79f977e40e4 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Sat, 18 May 2024 17:58:31 +0100 Subject: [PATCH 118/243] fix: spinner/loading --- .../scss/elements/forms/_buttons.scss | 11 ++++------- .../scss/elements/forms/_spinner.scss | 19 ++++++++----------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_buttons.scss b/assets/newspack-ui/scss/elements/forms/_buttons.scss index 6015f54a4f..5c64e2ffbd 100644 --- a/assets/newspack-ui/scss/elements/forms/_buttons.scss +++ b/assets/newspack-ui/scss/elements/forms/_buttons.scss @@ -202,15 +202,15 @@ } &::before { - animation: button-loading 1s infinite linear; - border: 2px solid; + animation: button-loading 900ms infinite linear; + border: 1.5px solid; border-color: currentcolor currentcolor transparent transparent; border-radius: 50%; content: ''; display: block; - height: var( --newspack-ui-spacer-3 ); + height: calc( var( --newspack-ui-spacer-base ) * 2.25 ); position: absolute; - width: var( --newspack-ui-spacer-3 ); + width: calc( var( --newspack-ui-spacer-base ) * 2.25 ); } } } @@ -220,9 +220,6 @@ 0% { transform: rotate( 0deg ); } - 50% { - transform: rotate( 180deg ); - } 100% { transform: rotate( 360deg ); } diff --git a/assets/newspack-ui/scss/elements/forms/_spinner.scss b/assets/newspack-ui/scss/elements/forms/_spinner.scss index c4fdc7f852..8108e164b7 100644 --- a/assets/newspack-ui/scss/elements/forms/_spinner.scss +++ b/assets/newspack-ui/scss/elements/forms/_spinner.scss @@ -1,24 +1,24 @@ .newspack-ui { &__spinner { align-items: center; - background: #fff; - border-radius: 5px; + background: var( --newspack-ui-color-neutral-0 ); + border-radius: var( --newspack-ui-border-radius-m ); display: flex; height: 100%; justify-content: center; left: 50%; - opacity: 0.5; + opacity: 0.7; position: absolute; top: 50%; transform: translate( -50%, -50% ); width: 100%; > span { - animation: spin 1s infinite linear; - border: 2px solid var( --newspack-ui-color-body-bg ); - border-top-color: var( --newspack-ui-color-neutral-70 ); + animation: spin 900ms infinite linear; + border: 1.5px solid; + border-color: var( --newspack-ui-color-neutral-90 ) var( --newspack-ui-color-neutral-90 ) var( --newspack-ui-color-body-bg ) var( --newspack-ui-color-body-bg ); border-radius: 50%; - height: 25px; - width: 25px; + height: calc( var( --newspack-ui-spacer-base ) * 2.25 ); + width: calc( var( --newspack-ui-spacer-base ) * 2.25 );; } } } @@ -27,9 +27,6 @@ 0% { transform: rotate( 0deg ); } - 50% { - transform: rotate( 180deg ); - } 100% { transform: rotate( 360deg ); } From 628f1fe2e3a011e5b6d2f736561b8ef233c35141 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Sat, 18 May 2024 18:01:22 +0100 Subject: [PATCH 119/243] fix: input wrong padding --- assets/newspack-ui/scss/elements/forms/_text-inputs.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/newspack-ui/scss/elements/forms/_text-inputs.scss b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss index e3ecfe310d..782dfbd975 100644 --- a/assets/newspack-ui/scss/elements/forms/_text-inputs.scss +++ b/assets/newspack-ui/scss/elements/forms/_text-inputs.scss @@ -24,7 +24,7 @@ font-family: var( --newspack-ui-font-family); font-size: var( --newspack-ui-font-size-s ); line-height: var( --newspack-ui-line-height-l ); - padding: calc( var( --newspack-ui-spacer-2 ) - 1px ) calc( var( --newspack-ui-spacer-3 ) - 1px ); + padding: calc( var( --newspack-ui-spacer-2 ) - 1px ) calc( var( --newspack-ui-spacer-2 ) - 1px ); transition: background-color 125ms ease-in-out, border-color 125ms ease-in-out, outline 125ms ease-in-out; width: 100%; From cb3462f486794b890df0c29a7aa0b9e9e44a618e Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Sat, 18 May 2024 18:04:13 +0100 Subject: [PATCH 120/243] feat: add 2xs border-radius --- assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss | 2 +- assets/newspack-ui/scss/elements/misc/_badge.scss | 2 +- assets/newspack-ui/scss/variables/_index.scss | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss index df4bdf7a80..b2c0aaa2b4 100644 --- a/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss +++ b/assets/newspack-ui/scss/elements/forms/_checkbox-radio.scss @@ -43,7 +43,7 @@ } input[type='checkbox'] { - border-radius: var( --newspack-ui-border-radius-xs ); + border-radius: var( --newspack-ui-border-radius-2xs ); &::before { background: transparent diff --git a/assets/newspack-ui/scss/elements/misc/_badge.scss b/assets/newspack-ui/scss/elements/misc/_badge.scss index 33271b0ae3..2da29e1015 100644 --- a/assets/newspack-ui/scss/elements/misc/_badge.scss +++ b/assets/newspack-ui/scss/elements/misc/_badge.scss @@ -1,6 +1,6 @@ .newspack-ui__badge { background: var( --newspack-ui-color-neutral-0 ); - border-radius: var( --newspack-ui-border-radius-xs ); + border-radius: var( --newspack-ui-border-radius-2xs ); color: var( --newspack-ui-color-neutral-90 ); display: inline-grid; font-size: var( --newspack-ui-font-size-xs ); diff --git a/assets/newspack-ui/scss/variables/_index.scss b/assets/newspack-ui/scss/variables/_index.scss index 1acd68a9ed..c1d61054e1 100644 --- a/assets/newspack-ui/scss/variables/_index.scss +++ b/assets/newspack-ui/scss/variables/_index.scss @@ -12,5 +12,6 @@ // Border radius - not ems because the font size of the element itself caused a cascade. --newspack-ui-border-radius-m: 6px; --newspack-ui-border-radius-s: 4px; - --newspack-ui-border-radius-xs: 2px; + --newspack-ui-border-radius-xs: 3px; + --newspack-ui-border-radius-2xs: 2px; } From 031a11cc62456d6e08cb0af64ec45c4ce1538313 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Sat, 18 May 2024 18:10:58 +0100 Subject: [PATCH 121/243] fix: svg missing colour (block theme) --- assets/newspack-ui/scss/elements/_icons.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/newspack-ui/scss/elements/_icons.scss b/assets/newspack-ui/scss/elements/_icons.scss index 6c4dba8706..52f7c0fa45 100644 --- a/assets/newspack-ui/scss/elements/_icons.scss +++ b/assets/newspack-ui/scss/elements/_icons.scss @@ -23,5 +23,9 @@ background: var( --newspack-ui-color-warning-30 ); color: var( --newspack-ui-color-body-bg ); } + + svg { + fill: currentcolor; + } } } From 5edf83b677859c68a893083c198543e0a1525d2a Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Sat, 18 May 2024 18:11:30 +0100 Subject: [PATCH 122/243] feat: update segmented control button hover/focus styles --- .../scss/elements/_segmented-control.scss | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/assets/newspack-ui/scss/elements/_segmented-control.scss b/assets/newspack-ui/scss/elements/_segmented-control.scss index 974351134f..753bea62e9 100644 --- a/assets/newspack-ui/scss/elements/_segmented-control.scss +++ b/assets/newspack-ui/scss/elements/_segmented-control.scss @@ -17,7 +17,22 @@ .newspack-ui__button { background: transparent; border: 1px solid transparent; + border-radius: var( --newspack-ui-border-radius-xs ); color: var( --newspack-ui-color-neutral-60 ); + cursor: pointer; + + &:hover { + background: transparent; + } + + &:focus { + outline: none; + } + + &:focus-visible { + outline: 2px solid var( --newspack-ui-color-button-bg ); + outline-offset: 2px ; + } &:not( :last-child ) { margin: 0; From 4ef953e4d89effa8c53be776d5b5493d5676d9df Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Mon, 20 May 2024 14:42:17 -0400 Subject: [PATCH 123/243] feat(ras-acc): use newsletters subscription lists setting to manage post-checkout newsletter signup (#3105) This PR: - Updates the Newsletter Subscription List setting copy to reflect the setting will also apply to checkout - Filters the post-checkout newsletter lists to include only lists that the reader is not signed up for and are not premium --- .../views/reader-activation/index.js | 7 ++- .../class-reader-activation.php | 62 +++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/assets/wizards/engagement/views/reader-activation/index.js b/assets/wizards/engagement/views/reader-activation/index.js index 07dc6163fa..751c251700 100644 --- a/assets/wizards/engagement/views/reader-activation/index.js +++ b/assets/wizards/engagement/views/reader-activation/index.js @@ -332,9 +332,12 @@ export default withWizardScreen( ( { wizardApiFetch } ) => { $list ) { + // Skip any lists the reader is already signed up for. + if ( in_array( $list_id, $current_lists, true ) ) { + continue; + } + + // Skip any premium lists since the reader has already made a purchase at this stage. + if ( method_exists( '\Newspack_Newsletters\Plugins\Woocommerce_Memberships', 'is_subscription_list_tied_to_plan' ) && \Newspack_Newsletters\Plugins\Woocommerce_Memberships::is_subscription_list_tied_to_plan( $list['db_id'] ) ) { + continue; + } + + $registration_lists[ $list_id ] = $list; + } + + /** + * Filters the newsletters lists that should be rendered after checkout. + * + * @param array $registration_lists Array of newsletter lists. + */ + return apply_filters( 'newspack_post_registration_newsletters_lists', $registration_lists ); + } + + /** + * Get all available newsletter lists. + * + * @return array + */ + public static function get_available_newsletter_lists() { if ( ! method_exists( 'Newspack_Newsletters_Subscription', 'get_lists' ) ) { return []; } From a8a1f1929a37f7de1e65754a298bbc56bb75b9a1 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Mon, 20 May 2024 14:46:27 -0400 Subject: [PATCH 124/243] feat(ras-acc): update newsletters palette on theme primary color updates (#3083) These changes ensure we are updating the newsletter color palette option with the latest primary theme colors before creating transactional emails from templates OR before triggering an update to email HTML when updating a sites primary newspack theme colors. --- includes/emails/class-emails.php | 75 +++++++++++++++++++++++--------- includes/util.php | 2 +- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/includes/emails/class-emails.php b/includes/emails/class-emails.php index f82bf76cff..681e45c50b 100644 --- a/includes/emails/class-emails.php +++ b/includes/emails/class-emails.php @@ -28,7 +28,7 @@ public static function init() { add_action( 'enqueue_block_editor_assets', [ __CLASS__, 'enqueue_block_editor_assets' ] ); add_filter( 'newspack_newsletters_email_editor_cpts', [ __CLASS__, 'register_email_cpt_with_email_editor' ] ); add_filter( 'newspack_newsletters_allowed_editor_actions', [ __CLASS__, 'register_scripts_enqueue_with_email_editor' ] ); - add_action( 'update_option_theme_mods_' . get_template(), [ __CLASS__, 'maybe_update_email_templates' ], 10, 2 ); + add_action( 'update_option_theme_mods_' . ( wp_get_theme()->parent() ? get_stylesheet() : get_template() ), [ __CLASS__, 'maybe_update_email_templates' ], 10, 2 ); add_action( 'admin_head', [ __CLASS__, 'inject_dynamic_email_template_styles' ] ); } @@ -488,6 +488,17 @@ public static function get_email_config_by_type( $type ) { /** Only attempt to create the email post if wp-includes/pluggable.php is loaded. */ return false; } else { + // Make sure newsletters color palette is updated with latest theme colors. + if ( self::supports_emails() && method_exists( '\Newspack_Newsletters', 'update_color_palette' ) ) { + $theme_colors = newspack_get_theme_colors(); + \Newspack_Newsletters::update_color_palette( + [ + 'primary' => $theme_colors['primary_color'], + 'primary-text' => $theme_colors['primary_text_color'], + ] + ); + } + $email_post_data = self::load_email_template( $type ); if ( ! $email_post_data ) { Logger::error( 'Error: could not retrieve template for type: ' . $type ); @@ -630,12 +641,30 @@ public static function get_password_reset_url( $user, $key ) { * @return void */ public static function maybe_update_email_templates( $previous_value, $updated_value ) { + // Do nothing if newsletters is not active. + if ( ! self::supports_emails() ) { + return; + } + // Check for theme mod color settings in case a non-newspack theme is installed. - if ( ! isset( $previous_value['primary_color_hex'], $previous_value['secondary_color_hex'], $updated_value['primary_color_hex'], $updated_value['secondary_color_hex'] ) ) { + if ( ! isset( $previous_value['primary_color_hex'], $updated_value['primary_color_hex'] ) ) { return; } - if ( $previous_value['primary_color_hex'] !== $updated_value['primary_color_hex'] || $previous_value['secondary_color_hex'] !== $updated_value['secondary_color_hex'] ) { + if ( $previous_value['primary_color_hex'] !== $updated_value['primary_color_hex'] ) { + // Update the newsletters color palette. + $updated = \Newspack_Newsletters::update_color_palette( + [ + 'primary' => $updated_value['primary_color_hex'], + 'primary-text' => newspack_get_color_contrast( $updated_value['primary_color_hex'] ), + ] + ); + + if ( ! $updated ) { + Logger::error( 'There was an error updating the newsletters color palette.' ); + } + + // Trigger an update of all email templates to regenerate HTML. $templates = get_posts( [ 'post_type' => self::POST_TYPE, @@ -645,26 +674,22 @@ public static function maybe_update_email_templates( $previous_value, $updated_v ); foreach ( $templates as $template ) { - wp_update_post( [ 'ID' => $template->ID ] ); - } - - if ( class_exists( 'Newspack_Newsletters' ) ) { - // Update newsletters color palette option so emails reflect the new colors. - $request = new \WP_REST_Request( 'POST', '/newspack-newsletters/v1/color-palette' ); - $request->set_body( - wp_json_encode( - [ - 'primary' => $updated_value['primary_color_hex'], - 'primary-text' => newspack_get_color_contrast( $updated_value['primary_color_hex'] ), - ] - ) + // Find/replace the old hex values with the new ones in the rendered email HTML. + $email_html = get_post_meta( $template->ID, \Newspack_Newsletters::EMAIL_HTML_META, true ); + $email_html = str_replace( + [ + $previous_value['primary_color_hex'], + newspack_get_color_contrast( $previous_value['primary_color_hex'] ), + ], + [ + $updated_value['primary_color_hex'], + newspack_get_color_contrast( $updated_value['primary_color_hex'] ), + ], + $email_html ); + update_post_meta( $template->ID, \Newspack_Newsletters::EMAIL_HTML_META, $email_html ); - $response = rest_do_request( $request ); - - if ( $response->is_error() ) { - Logger::error( 'Error updating newsletters color palette: ' . $response->as_error()->get_error_message() ); - } + wp_update_post( [ 'ID' => $template->ID ] ); } } } @@ -687,6 +712,14 @@ public static function inject_dynamic_email_template_styles() { .-has-primary-text-color a { color: !important; } + + .is-style-filled-primary-text li { + background: transparent !important; + } + + .is-style-filled-primary-text li svg { + color: !important; + } '
'; diff --git a/includes/templates/reader-activation-emails/otp.php b/includes/templates/reader-activation-emails/otp.php index 3567f18639..5f73a8a44d 100644 --- a/includes/templates/reader-activation-emails/otp.php +++ b/includes/templates/reader-activation-emails/otp.php @@ -280,29 +280,29 @@

' . __( 'Sign in', 'newspack-plugin' ) . '

-

' . sprintf( /* Translators: s: the site title. */ __( 'Here\'s your one-time password to sign in to %s', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+

' . sprintf( /* Translators: s: the site title. */ __( 'Here\'s your one-time password to sign in to %s', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

-

*MAGIC_LINK_OTP*

+

*MAGIC_LINK_OTP*

-

' . sprintf( /* Translators: 1: Opening HTML anchor tag. 2: Closing HTML anchor tag. */ __( 'Copy your one-time password, or click the magic link below to finish signing in. You also have the option to %1$screate a password%2$s for your account.', 'newspack-plugin' ), '', '' ) . +

' . sprintf( /* Translators: 1: Opening HTML anchor tag. 2: Closing HTML anchor tag. */ __( 'Copy your one-time password, or click the magic link below to finish signing in. You also have the option to %1$screate a password%2$s for your account.', 'newspack-plugin' ), '', '' ) . '

+
-

' . __( 'You can also copy and paste this link in your browser:', 'newspack-plugin' ) . '
*MAGIC_LINK_URL*

+

' . __( 'You can also copy and paste this link in your browser:', 'newspack-plugin' ) . '
*MAGIC_LINK_URL*

-

' . __( 'Frequently Asked Questions', 'newspack' ) . '

+

' . __( 'Frequently Asked Questions', 'newspack' ) . '

-

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

+

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

-

' . __( 'Can I still create a password?', 'newspack' ) . '
' . sprintf( /* Translators: 1: opening HTML anchor tag 2: closing HTML anchor tag */ __( 'Yes. For security reasons, we recommend signing in with Google or using a one-time code sent to your email, but you can set a password if you prefer. %1$sClick here%2$s to create a password.', 'newspack' ), '', '' ) . '

+

' . __( 'Can I still create a password?', 'newspack' ) . '
' . sprintf( /* Translators: 1: opening HTML anchor tag 2: closing HTML anchor tag */ __( 'Yes. For security reasons, we recommend signing in with Google or using a one-time code sent to your email, but you can set a password if you prefer. %1$sClick here%2$s to create a password.', 'newspack' ), '', '' ) . '

' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-activation-emails/password-reset.php b/includes/templates/reader-activation-emails/password-reset.php index 2cf6758f0e..47c31382d7 100644 --- a/includes/templates/reader-activation-emails/password-reset.php +++ b/includes/templates/reader-activation-emails/password-reset.php @@ -243,16 +243,16 @@

' . __( 'Reset password', 'newspack-plugin' ) . '

-

' . __( 'You have just requested a password reset for your account associated with this email address.', 'newspack-plugin' ) . '

+

' . __( 'You have just requested a password reset for your account associated with this email address.', 'newspack-plugin' ) . '

+
-

' . sprintf( /* Translators: 1: Opening HTML anchor tag containing Newspack support link. 2: Closing HTML anchor tag. */ __( 'If you continue to have issues signing in, please %1$scontact us%2$s.', 'newspack-plugin' ), '', '' ) . '

+

' . sprintf( /* Translators: 1: Opening HTML anchor tag containing Newspack support link. 2: Closing HTML anchor tag. */ __( 'If you continue to have issues signing in, please %1$scontact us%2$s.', 'newspack-plugin' ), '', '' ) . '

' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to reset your password to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to reset your password to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-activation-emails/verification.php b/includes/templates/reader-activation-emails/verification.php index 198d400e86..5787b3b83b 100644 --- a/includes/templates/reader-activation-emails/verification.php +++ b/includes/templates/reader-activation-emails/verification.php @@ -243,9 +243,9 @@

' . __( 'Verify your email', 'newspack-plugin' ) . '

-

' . sprintf( /* Translators: s: The site name. */ __( 'Thanks for creating an account with %s! Click the button below to verify the email address for your account.', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+

' . sprintf( /* Translators: s: The site name. */ __( 'Thanks for creating an account with %s! Click the button below to verify the email address for your account.', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+ @@ -253,7 +253,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you have registered on %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you have registered on %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-revenue-emails/cancellation.php b/includes/templates/reader-revenue-emails/cancellation.php index 54670ecdc7..35ac93a699 100644 --- a/includes/templates/reader-revenue-emails/cancellation.php +++ b/includes/templates/reader-revenue-emails/cancellation.php @@ -35,9 +35,13 @@ -
+
+ + + +
@@ -237,16 +241,16 @@

*CANCELLATION_TITLE*

-

' . sprintf( /* Translators: 1: the cancellation type (subscription or recurring donation). 2: the site title. */ __( 'This is to confirm the cancellation of your %1$s to %2$s. We\'re sorry to see you go! If you\'d like to restart your %1$s, you can do so by clicking the button below.', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_TITLE*' ) . '

+

' . sprintf( /* Translators: 1: the cancellation type (subscription or recurring donation). 2: the site title. */ __( 'This is to confirm the cancellation of your %1$s to %2$s. We\'re sorry to see you go! If you\'d like to restart your %1$s, you can do so by clicking the button below.', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_TITLE*' ) . '

+
-

' . sprintf( /* Translators: s: site admin email address. */ __( 'If you have any questions, you can reach us at %s. We appreciate your support.', 'newspack-plugin' ), '*CONTACT_EMAIL*' ) . '

+

' . sprintf( /* Translators: s: site admin email address. */ __( 'If you have any questions, you can reach us at %s. We appreciate your support.', 'newspack-plugin' ), '*CONTACT_EMAIL*' ) . '

' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you cancelled your %1$s to %2$s', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_URL*' ) . '

+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you cancelled your %1$s to %2$s', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-revenue-emails/receipt.php b/includes/templates/reader-revenue-emails/receipt.php index ec93923c9e..aac9458dde 100644 --- a/includes/templates/reader-revenue-emails/receipt.php +++ b/includes/templates/reader-revenue-emails/receipt.php @@ -251,20 +251,20 @@

' . __( 'Thank you!', 'newspack-plugin' ) . '

-

' . sprintf( /* Translators: s: the site title. */ __( 'Thank you for supporting %s. Here is a receipt for your recent transaction:', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+

' . sprintf( /* Translators: s: the site title. */ __( 'Thank you for supporting %s. Here is a receipt for your recent transaction:', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

-

' . __( 'Amount paid', 'newspack' ) . '

*AMOUNT*

+

' . __( 'Amount paid', 'newspack' ) . '

*AMOUNT*

-

' . __( 'Date paid', 'newspack' ) . '

*DATE*

+

' . __( 'Date paid', 'newspack' ) . '

*DATE*

-

' . __( 'Payment method', 'newspack' ) . '

*PAYMENT_METHOD*

+

' . __( 'Payment method', 'newspack' ) . '

*PAYMENT_METHOD*

-

' . sprintf( /* Translators: 1: site admin email address. 2: my account page link. */ __( 'If you have any questions, you can reach us at %1$s. You can download a copy of this receipt at %2$s.', 'newspack-plugin' ), '*CONTACT_EMAIL*', '*RECEIPT_URL*' ) . '

+

' . sprintf( /* Translators: 1: site admin email address. 2: my account page link. */ __( 'If you have any questions, you can reach us at %1$s. You can download a copy of this receipt at %2$s.', 'newspack-plugin' ), '*CONTACT_EMAIL*', '*RECEIPT_URL*' ) . '

' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-revenue-emails/welcome.php b/includes/templates/reader-revenue-emails/welcome.php index 4a86869326..3b6a522a7a 100644 --- a/includes/templates/reader-revenue-emails/welcome.php +++ b/includes/templates/reader-revenue-emails/welcome.php @@ -267,24 +267,24 @@

' . __( 'Thank you and welcome!', 'newspack-plugin' ) . '

-

' . sprintf( /* Translators: s: the site title. */ __( 'Thank you for supporting %s. Your new account has been created and is ready to use.', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+

' . sprintf( /* Translators: s: the site title. */ __( 'Thank you for supporting %s. Your new account has been created and is ready to use.', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

+
-

' . __( 'Here is a receipt for your recent transaction:', 'newspack-plugin' ) . '

+

' . __( 'Here is a receipt for your recent transaction:', 'newspack-plugin' ) . '

-

' . __( 'Amount paid', 'newspack' ) . '

*AMOUNT*

+

' . __( 'Amount paid', 'newspack' ) . '

*AMOUNT*

-

' . __( 'Date paid', 'newspack' ) . '

*DATE*

+

' . __( 'Date paid', 'newspack' ) . '

*DATE*

-

' . __( 'Payment method', 'newspack' ) . '

*PAYMENT_METHOD*

+

' . __( 'Payment method', 'newspack' ) . '

*PAYMENT_METHOD*

-

' . sprintf( /* Translators: 1: site admin email address. 2: my account page link. */ __( 'If you have any questions, you can reach us at %1$s. You can download a copy of this receipt at %2$s.', 'newspack-plugin' ), '*CONTACT_EMAIL*', '*RECEIPT_URL*' ) . '

+

' . sprintf( /* Translators: 1: site admin email address. 2: my account page link. */ __( 'If you have any questions, you can reach us at %1$s. You can download a copy of this receipt at %2$s.', 'newspack-plugin' ), '*CONTACT_EMAIL*', '*RECEIPT_URL*' ) . '

' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/src/other-scripts/emails/style.scss b/src/other-scripts/emails/style.scss index 9ed863e0cc..4710d9ebac 100644 --- a/src/other-scripts/emails/style.scss +++ b/src/other-scripts/emails/style.scss @@ -2,7 +2,15 @@ display: none; } -.editor-styles-wrapper .block-editor-block-list__layout .wp-block-button { - margin-left: 0 !important; - margin-right: 0 !important; +.editor-styles-wrapper .block-editor-block-list__layout { + :not(code) { + font-family: Arial, Helvetica, sans-serif !important; + } + + .wp-block-button { + margin-left: 0 !important; + margin-right: 0 !important; + padding: 0 !important; + } } + From 5f00cbb9a1f5d1826e0cdd3679677b72145b9d3f Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Mon, 12 Aug 2024 10:45:24 -0400 Subject: [PATCH 184/243] fix(ras-acc): transactional emails helper text and template updates (#3323) Some fixes to email templates and the helper text that appears in wp-admin for the sign in emails: - Template FAQ section update (makes sure the magic link section is present in gmail) - Sign in emails helper text updated --- includes/reader-activation/class-reader-activation-emails.php | 4 ++-- includes/templates/reader-activation-emails/magic-link.php | 4 ++-- includes/templates/reader-activation-emails/otp.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/reader-activation/class-reader-activation-emails.php b/includes/reader-activation/class-reader-activation-emails.php index 8653b36c86..2eb9d52055 100644 --- a/includes/reader-activation/class-reader-activation-emails.php +++ b/includes/reader-activation/class-reader-activation-emails.php @@ -76,7 +76,7 @@ public static function add_email_configs( $configs ) { $configs[ self::EMAIL_TYPES['MAGIC_LINK'] ] = [ 'name' => self::EMAIL_TYPES['MAGIC_LINK'], 'label' => __( 'Login link', 'newspack' ), - 'description' => __( 'Email with a login link.', 'newspack' ), + 'description' => __( 'Email sent to users with a login link generated by Admin user or when one-time password is disabled.', 'newspack' ), 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-activation-emails/magic-link.php', 'editor_notice' => __( 'This email will be sent to a reader when they request a login link.', 'newspack' ), 'available_placeholders' => array_merge( @@ -92,7 +92,7 @@ public static function add_email_configs( $configs ) { $configs[ self::EMAIL_TYPES['OTP_AUTH'] ] = [ 'name' => self::EMAIL_TYPES['OTP_AUTH'], 'label' => __( 'Login one-time password', 'newspack' ), - 'description' => __( 'Email with a one-time password and login link.', 'newspack' ), + 'description' => __( 'Email sent to users with a one-time password and login link.', 'newspack' ), 'template' => dirname( NEWSPACK_PLUGIN_FILE ) . '/includes/templates/reader-activation-emails/otp.php', 'editor_notice' => __( 'This email will be sent to a reader when they request a login link and a one-time password is available.', 'newspack' ), 'available_placeholders' => array_merge( diff --git a/includes/templates/reader-activation-emails/magic-link.php b/includes/templates/reader-activation-emails/magic-link.php index d27a545517..89cc13e246 100644 --- a/includes/templates/reader-activation-emails/magic-link.php +++ b/includes/templates/reader-activation-emails/magic-link.php @@ -277,11 +277,11 @@
-

' . __( 'Or copy and paste the link in your browser:', 'newspack-plugin' ) . ' *MAGIC_LINK_URL*

+

' . __( 'Or copy and paste the link in your browser:', 'newspack-plugin' ) . ' *MAGIC_LINK_URL*

-

' . __( 'Frequently Asked Questions', 'newspack' ) . '

+

' . __( 'Frequently Asked Questions', 'newspack' ) . '

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

diff --git a/includes/templates/reader-activation-emails/otp.php b/includes/templates/reader-activation-emails/otp.php index 5f73a8a44d..87eb75c495 100644 --- a/includes/templates/reader-activation-emails/otp.php +++ b/includes/templates/reader-activation-emails/otp.php @@ -295,7 +295,7 @@

' . __( 'Frequently Asked Questions', 'newspack' ) . '

-

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

+

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

' . __( 'Can I still create a password?', 'newspack' ) . '
' . sprintf( /* Translators: 1: opening HTML anchor tag 2: closing HTML anchor tag */ __( 'Yes. For security reasons, we recommend signing in with Google or using a one-time code sent to your email, but you can set a password if you prefer. %1$sClick here%2$s to create a password.', 'newspack' ), '', '' ) . '

From 69cab554144abd051bd81fb8ad261aea6a59a3bb Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Wed, 14 Aug 2024 10:12:54 -0400 Subject: [PATCH 185/243] fix(ras-acc): reset otp flow on sign in modal close (#3305) This PR "resets" the OTP state of the login form once the OTP timer runs out. Previously, if a reader opened the login form with an account with a password set, but then chose to sign in via OTP, the auth form would "remember" this OTP login state and prompt for OTP the next time the auth modal was opened. --- includes/class-magic-link.php | 32 ++++++++++ .../class-reader-activation.php | 8 ++- src/reader-activation-auth/auth-form.js | 59 ++++++++++--------- src/reader-activation-auth/auth-modal.js | 7 +++ 4 files changed, 78 insertions(+), 28 deletions(-) diff --git a/includes/class-magic-link.php b/includes/class-magic-link.php index 22b8241673..4e59f26359 100644 --- a/includes/class-magic-link.php +++ b/includes/class-magic-link.php @@ -374,6 +374,38 @@ public static function generate_token( $user ) { return $token_data; } + /** + * Check for magic link tokens generated within the last 60 seconds. + * + * @param \WP_User $user User to check the active magic link token for. + * + * @return bool|\WP_Error + */ + public static function has_active_token( $user ) { + if ( ! self::can_magic_link( $user->ID ) ) { + return new \WP_Error( 'newspack_magic_link_invalid_user', __( 'Invalid user.', 'newspack' ) ); + } + + $now = time(); + $tokens = \get_user_meta( $user->ID, self::TOKENS_META, true ); + + $expire = $now - MINUTE_IN_SECONDS; + if ( ! empty( $tokens ) ) { + foreach ( $tokens as $index => $token_data ) { + /** Clear expired tokens. */ + if ( $token_data['time'] < $expire ) { + unset( $tokens[ $index ] ); + } + } + } + + if ( empty( $tokens ) ) { + return false; + } + + return true; + } + /** * Generate a magic link. * diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index e1d4af9220..ad919c50ae 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -226,6 +226,7 @@ private static function get_reader_activation_labels( $key = null ) { 'invalid_password' => __( 'Please enter a password.', 'newspack-plugin' ), 'invalid_display' => __( 'Display name cannot match your email address. Please choose a different display name.', 'newspack-plugin' ), 'blocked_popup' => __( 'The popup has been blocked. Allow popups for the site and try again.', 'newspack-plugin' ), + 'code_sent' => __( 'Code sent! Check your inbox.', 'newspack-plugin' ), 'code_resent' => __( 'Code resent! Check your inbox.', 'newspack-plugin' ), 'create_account' => __( 'Create an account', 'newspack-plugin' ), 'signin' => [ @@ -1298,7 +1299,7 @@ public static function render_auth_form( $in_modal = true ) { ?>

- + @@ -1683,6 +1684,7 @@ public static function process_auth_form() { if ( ! isset( $_POST[ self::AUTH_FORM_ACTION ] ) ) { return; } + $action = isset( $_POST['action'] ) ? \sanitize_text_field( $_POST['action'] ) : ''; $referer = isset( $_POST['referer'] ) ? \sanitize_text_field( $_POST['referer'] ) : ''; $current_page_url = \wp_parse_url( \wp_get_raw_referer() ); // Referer is the current page URL because the form is submitted via AJAX. @@ -1738,6 +1740,10 @@ public static function process_auth_form() { switch ( $action ) { case 'signin': + if ( Magic_Link::has_active_token( $user ) ) { + $payload['action'] = 'otp'; + return self::send_auth_form_response( $payload, false ); + } if ( self::is_reader_without_password( $user ) ) { $sent = Magic_Link::send_email( $user, $current_page_url ); if ( true !== $sent ) { diff --git a/src/reader-activation-auth/auth-form.js b/src/reader-activation-auth/auth-form.js index 3a949376b4..66bbc0f4d1 100644 --- a/src/reader-activation-auth/auth-form.js +++ b/src/reader-activation-auth/auth-form.js @@ -34,7 +34,8 @@ window.newspackRAS.push( function ( readerActivation ) { const passwordInput = form.querySelector( 'input[name="password"]' ); const submitButtons = form.querySelectorAll( '[type="submit"]' ); const backButtons = container.querySelectorAll( '[data-back]' ); - const sendCodeButtons = container.querySelectorAll( '[data-send-code]' ); + const sendCodeButton = container.querySelector( '[data-send-code]' ); + const resendCodeButton = container.querySelector( '[data-resend-code]' ); const messageContentElement = container.querySelector( '.response' ); /** @@ -116,6 +117,7 @@ window.newspackRAS.push( function ( readerActivation ) { backButtons.forEach( backButton => { backButton.addEventListener( 'click', function ( ev ) { ev.preventDefault(); + form.setMessageContent(); container.setFormAction( 'signin', true ); } ); } ); @@ -124,36 +126,29 @@ window.newspackRAS.push( function ( readerActivation ) { * Handle OTP Timer. */ const handleOTPTimer = () => { - if ( ! sendCodeButtons.length ) { + if ( ! resendCodeButton ) { return; } - sendCodeButtons.forEach( button => { - button.originalButtonText = button.textContent; - if ( button.otpTimerInterval ) { - clearInterval( button.otpTimerInterval ); - } - const updateButton = () => { - const remaining = readerActivation.getOTPTimeRemaining(); - if ( remaining ) { - button.textContent = `${ button.originalButtonText } (${ formatTime( remaining ) })`; - button.disabled = true; - } else { - button.textContent = button.originalButtonText; - button.disabled = false; - clearInterval( button.otpTimerInterval ); - } - }; + resendCodeButton.originalButtonText = resendCodeButton.textContent.replace( /\s\(\d{1,}:\d{2}\)/, '' ); + const updateButton = () => { const remaining = readerActivation.getOTPTimeRemaining(); if ( remaining ) { - button.otpTimerInterval = setInterval( updateButton, 1000 ); - updateButton(); + resendCodeButton.textContent = `${ resendCodeButton.originalButtonText } (${ formatTime( remaining ) })`; + } else { + resendCodeButton.textContent = resendCodeButton.originalButtonText; + clearInterval( resendCodeButton.otpTimerInterval ); } - } ); + resendCodeButton.disabled = !!remaining; + }; + const remaining = readerActivation.getOTPTimeRemaining(); + if ( remaining ) { + resendCodeButton.otpTimerInterval = setInterval( updateButton, 1000 ); + updateButton(); + } }; - if ( sendCodeButtons.length ) { - handleOTPTimer(); - sendCodeButtons.forEach( button => { + if ( sendCodeButton || resendCodeButton ) { + [ sendCodeButton, resendCodeButton ].forEach( button => { button.addEventListener( 'click', function ( ev ) { form.setMessageContent(); ev.preventDefault(); @@ -182,9 +177,15 @@ window.newspackRAS.push( function ( readerActivation ) { body, } ) .then( () => { - form.setMessageContent( newspack_reader_activation_labels.code_resent ); + form.setMessageContent( + formAction === 'pwd' + ? newspack_reader_activation_labels.code_sent + : newspack_reader_activation_labels.code_resent + ); container.setFormAction( 'otp' ); - readerActivation.setOTPTimer(); + if ( ! readerActivation.getOTPTimeRemaining() ) { + readerActivation.setOTPTimer(); + } } ) .catch( e => { console.log( e ); // eslint-disable-line no-console @@ -407,13 +408,17 @@ window.newspackRAS.push( function ( readerActivation ) { .json() .then( ( { message, data } ) => { const status = res.status; + const prevEmail = readerActivation.getReader?.()?.email; if ( status === 200 ) { readerActivation.setReaderEmail( body.get( 'npe' ) ); } if ( data.action ) { container.setFormAction( data.action, true ); if ( data.action === 'otp' ) { - readerActivation.setOTPTimer(); + form.setMessageContent( newspack_reader_activation_labels.code_sent ); + if ( data.email !== prevEmail || ! readerActivation.getOTPTimeRemaining() ) { + readerActivation.setOTPTimer(); + } handleOTPTimer(); } } else { diff --git a/src/reader-activation-auth/auth-modal.js b/src/reader-activation-auth/auth-modal.js index 6e1224f870..9fd1da992a 100644 --- a/src/reader-activation-auth/auth-modal.js +++ b/src/reader-activation-auth/auth-modal.js @@ -123,6 +123,13 @@ export function openAuthModal( config = {} ) { } container.setFormAction( initialFormAction, true ); + // Default to signin action if otp and timer has expired. + if ( + initialFormAction === 'otp' && + window?.newspackReaderActivation?.getOTPTimeRemaining() <= 0 + ) { + container.setFormAction( 'signin' ); + } document.body.classList.add( 'newspack-signin' ); document.body.style.overflow = 'hidden'; modal.setAttribute( 'data-state', 'open' ); From a21eb6f03ec0cb43a47ba67bff45afd09b180066 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Thu, 15 Aug 2024 10:34:33 -0400 Subject: [PATCH 186/243] fix(ras-acc): respect transactional email social icons alignment (#3339) This PR fixes an issue where the alignment of the transactional email social icons did not line up with the rest of the email content. --- includes/util.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/includes/util.php b/includes/util.php index 5d2d8eb197..d911ed7e77 100644 --- a/includes/util.php +++ b/includes/util.php @@ -560,10 +560,11 @@ function newspack_get_theme_colors() { * @return array An array containing block and html markup for social media services. */ function newspack_get_social_markup( $color = 'white' ) { - $cm = Configuration_Managers::configuration_manager_class_for_plugin_slug( 'wordpress_seo' ); - $social_urls = []; - $markup = [ - 'block_markup' => '
'; diff --git a/includes/templates/reader-activation-emails/magic-link.php b/includes/templates/reader-activation-emails/magic-link.php index 89cc13e246..a83b05ccb0 100644 --- a/includes/templates/reader-activation-emails/magic-link.php +++ b/includes/templates/reader-activation-emails/magic-link.php @@ -26,8 +26,8 @@ - -

' . __( 'Sign in', 'newspack-plugin' ) . '

+ +

' . __( 'Sign in', 'newspack-plugin' ) . '

@@ -68,8 +68,8 @@ @@ -271,7 +271,7 @@
-

' . __( 'Sign in', 'newspack-plugin' ) . '

+

' . __( 'Sign in', 'newspack-plugin' ) . '

' . sprintf( /* Translators: 1: Opening HTML anchor tag. 2: Closing HTML anchor tag. */ __( 'Click the magic link below to continue where you left off. You also have the option to %1$screate a password%2$s for your account.', 'newspack-plugin' ), '', '' ) . '

@@ -281,7 +281,7 @@

-

' . __( 'Frequently Asked Questions', 'newspack' ) . '

+

' . __( 'Frequently Asked Questions', 'newspack' ) . '

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

@@ -290,7 +290,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-activation-emails/otp.php b/includes/templates/reader-activation-emails/otp.php index 87eb75c495..b2ff3a62e8 100644 --- a/includes/templates/reader-activation-emails/otp.php +++ b/includes/templates/reader-activation-emails/otp.php @@ -26,16 +26,16 @@ - -

' . __( 'Sign in', 'newspack-plugin' ) . '

+ +

' . __( 'Sign in', 'newspack-plugin' ) . '

' . sprintf( /* Translators: s: the site title. */ __( 'Here\'s your one-time password to sign in to %s', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

- -

*MAGIC_LINK_OTP*

+ +

*MAGIC_LINK_OTP*

@@ -76,8 +76,8 @@ @@ -278,11 +278,11 @@
-

' . __( 'Sign in', 'newspack-plugin' ) . '

+

' . __( 'Sign in', 'newspack-plugin' ) . '

' . sprintf( /* Translators: s: the site title. */ __( 'Here\'s your one-time password to sign in to %s', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

-

*MAGIC_LINK_OTP*

+

*MAGIC_LINK_OTP*

' . sprintf( /* Translators: 1: Opening HTML anchor tag. 2: Closing HTML anchor tag. */ __( 'Copy your one-time password, or click the magic link below to finish signing in. You also have the option to %1$screate a password%2$s for your account.', 'newspack-plugin' ), '', '' ) . '

@@ -293,7 +293,7 @@

-

' . __( 'Frequently Asked Questions', 'newspack' ) . '

+

' . __( 'Frequently Asked Questions', 'newspack' ) . '

' . __( 'What is a magic link?', 'newspack' ) . '
' . __( 'It\’s a temporary, password-free link like the one above to help you quickly and securely verify your identity and sign in – all without needing to set a password.', 'newspack' ) . '

@@ -302,7 +302,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to sign in to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-activation-emails/password-reset.php b/includes/templates/reader-activation-emails/password-reset.php index 31d2d7d814..fffbb11c78 100644 --- a/includes/templates/reader-activation-emails/password-reset.php +++ b/includes/templates/reader-activation-emails/password-reset.php @@ -26,8 +26,8 @@ - -

' . __( 'Reset password', 'newspack-plugin' ) . '

+ +

' . __( 'Reset password', 'newspack-plugin' ) . '

@@ -59,8 +59,8 @@ $social_links . - ' -

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you requested to reset your password to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+ ' +

*SITE_CONTACT*
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you requested to reset your password to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

@@ -241,7 +241,7 @@
-

' . __( 'Reset password', 'newspack-plugin' ) . '

+

' . __( 'Reset password', 'newspack-plugin' ) . '

' . __( 'You have just requested a password reset for your account associated with this email address.', 'newspack-plugin' ) . '

@@ -252,7 +252,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to reset your password to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you requested to reset your password to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-activation-emails/verification.php b/includes/templates/reader-activation-emails/verification.php index 5787b3b83b..2535201022 100644 --- a/includes/templates/reader-activation-emails/verification.php +++ b/includes/templates/reader-activation-emails/verification.php @@ -26,8 +26,8 @@ - -

' . __( 'Verify your email', 'newspack-plugin' ) . '

+ +

' . __( 'Verify your email', 'newspack-plugin' ) . '

@@ -62,7 +62,7 @@ $social_links . ' -

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you registered to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you registered to %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; @@ -241,7 +241,7 @@
-

' . __( 'Verify your email', 'newspack-plugin' ) . '

+

' . __( 'Verify your email', 'newspack-plugin' ) . '

' . sprintf( /* Translators: s: The site name. */ __( 'Thanks for creating an account with %s! Click the button below to verify the email address for your account.', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

@@ -253,7 +253,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you have registered on %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you have registered on %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-revenue-emails/cancellation.php b/includes/templates/reader-revenue-emails/cancellation.php index 35ac93a699..e1cf29f57e 100644 --- a/includes/templates/reader-revenue-emails/cancellation.php +++ b/includes/templates/reader-revenue-emails/cancellation.php @@ -26,8 +26,8 @@ - -

*CANCELLATION_TITLE*

+ +

*CANCELLATION_TITLE*

@@ -58,7 +58,7 @@ $social_links . ' -

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you cancelled your %1$s to %2$s', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you cancelled your %1$s to %2$s', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_URL*' ) . '

@@ -239,7 +239,7 @@
-

*CANCELLATION_TITLE*

+

*CANCELLATION_TITLE*

' . sprintf( /* Translators: 1: the cancellation type (subscription or recurring donation). 2: the site title. */ __( 'This is to confirm the cancellation of your %1$s to %2$s. We\'re sorry to see you go! If you\'d like to restart your %1$s, you can do so by clicking the button below.', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_TITLE*' ) . '

@@ -250,7 +250,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you cancelled your %1$s to %2$s', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you cancelled your %1$s to %2$s', 'newspack-plugin' ), '*CANCELLATION_TYPE*', '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-revenue-emails/receipt.php b/includes/templates/reader-revenue-emails/receipt.php index aac9458dde..dbae18e24c 100644 --- a/includes/templates/reader-revenue-emails/receipt.php +++ b/includes/templates/reader-revenue-emails/receipt.php @@ -26,8 +26,8 @@ - -

' . __( 'Thank you!', 'newspack-plugin' ) . '

+ +

' . __( 'Thank you!', 'newspack-plugin' ) . '

@@ -72,7 +72,7 @@ $social_links . ' -

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

@@ -249,7 +249,7 @@
-

' . __( 'Thank you!', 'newspack-plugin' ) . '

+

' . __( 'Thank you!', 'newspack-plugin' ) . '

' . sprintf( /* Translators: s: the site title. */ __( 'Thank you for supporting %s. Here is a receipt for your recent transaction:', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

@@ -264,7 +264,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; diff --git a/includes/templates/reader-revenue-emails/welcome.php b/includes/templates/reader-revenue-emails/welcome.php index 3b6a522a7a..c19daafdad 100644 --- a/includes/templates/reader-revenue-emails/welcome.php +++ b/includes/templates/reader-revenue-emails/welcome.php @@ -26,8 +26,8 @@ - -

' . __( 'Thank you and welcome!', 'newspack-plugin' ) . '

+ +

' . __( 'Thank you and welcome!', 'newspack-plugin' ) . '

@@ -88,7 +88,7 @@ $social_links . ' -

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: 1: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

@@ -265,7 +265,7 @@
-

' . __( 'Thank you and welcome!', 'newspack-plugin' ) . '

+

' . __( 'Thank you and welcome!', 'newspack-plugin' ) . '

' . sprintf( /* Translators: s: the site title. */ __( 'Thank you for supporting %s. Your new account has been created and is ready to use.', 'newspack-plugin' ), '*SITE_TITLE*' ) . '

@@ -284,7 +284,7 @@
' . $social_links_html . '
-

' . sprintf( /* Translators: 1: site title 2: site base address. */ __( '%1$s - %2$s', 'newspack-plugin' ), '*SITE_TITLE*', '*SITE_ADDRESS*' ) . '
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

+

*SITE_CONTACT*
' . sprintf( /* Translators: s: link to site url. */ __( 'You received this email because you supported %s', 'newspack-plugin' ), '*SITE_URL*' ) . '

'; From e3794119f332e07002d28c89cd7df9d1150e3dec Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Mon, 19 Aug 2024 14:56:27 -0700 Subject: [PATCH 188/243] feat: trap focus in the newsletter modal --- src/reader-activation-newsletters/newsletters-modal.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/reader-activation-newsletters/newsletters-modal.js b/src/reader-activation-newsletters/newsletters-modal.js index ec7d7da805..657446925c 100644 --- a/src/reader-activation-newsletters/newsletters-modal.js +++ b/src/reader-activation-newsletters/newsletters-modal.js @@ -1,3 +1,5 @@ +import * as a11y from '../reader-activation-auth/accessibility.js'; + /** * Get the newsletters signup modal container. * @@ -91,6 +93,7 @@ export function openNewslettersSignupModal( config = {} ) { } modal.setAttribute( 'data-state', 'open' ); + a11y.trapFocus( modal ); if ( window?.newspackReaderActivation?.overlays ) { modal.overlayId = window.newspackReaderActivation.overlays.add(); } From 575da6ed86e04ba55c1325f01bddd0d0c5d8cae6 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 20 Aug 2024 10:38:54 -0700 Subject: [PATCH 189/243] fix: remove some duplication from selectors --- src/reader-activation-auth/accessibility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reader-activation-auth/accessibility.js b/src/reader-activation-auth/accessibility.js index b5dd0bb3f1..69bfd3f26b 100644 --- a/src/reader-activation-auth/accessibility.js +++ b/src/reader-activation-auth/accessibility.js @@ -7,8 +7,8 @@ export function trapFocus( currentModal ) { 'button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])'; const visibleFocusableEls = []; - const firstFocusableEl = currentModal.querySelectorAll( focusableEls )[ 0 ]; // get first element to be focused inside modal const focusableElsAll = currentModal.querySelectorAll( focusableEls ); + const firstFocusableEl = focusableElsAll?.[ 0 ]; // get first element to be focused inside modal // Get rid of elements that aren't visible: focusableElsAll.forEach( function ( el, index ) { From edb89fc862e7ea772e0c736a36d36ecf4d3cad1d Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 20 Aug 2024 13:58:19 -0700 Subject: [PATCH 190/243] fix: add check for focusable elements --- src/reader-activation-auth/accessibility.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/reader-activation-auth/accessibility.js b/src/reader-activation-auth/accessibility.js index 69bfd3f26b..afab8961b8 100644 --- a/src/reader-activation-auth/accessibility.js +++ b/src/reader-activation-auth/accessibility.js @@ -3,11 +3,17 @@ * See: https://uxdesign.cc/how-to-trap-focus-inside-modal-to-make-it-ada-compliant-6a50f9a70700 */ export function trapFocus( currentModal ) { + const focusableEls = 'button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])'; const visibleFocusableEls = []; - const focusableElsAll = currentModal.querySelectorAll( focusableEls ); + + // Make sure we have elements to focus on before continuing. + if ( 0 === focusableElsAll.length ) { + return false; + } + const firstFocusableEl = focusableElsAll?.[ 0 ]; // get first element to be focused inside modal // Get rid of elements that aren't visible: @@ -22,7 +28,6 @@ export function trapFocus( currentModal ) { document.addEventListener( 'keydown', function ( e ) { const isTabPressed = e.key === 'Tab' || e.keyCode === 9; - if ( ! isTabPressed ) { return; } From 9c781a2398e4ffeb7faa3aa7b7d4976058780be1 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 20 Aug 2024 16:03:44 -0700 Subject: [PATCH 191/243] fix: remove unused action --- includes/class-donations.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/includes/class-donations.php b/includes/class-donations.php index 95a7f33bba..caf8df9f18 100644 --- a/includes/class-donations.php +++ b/includes/class-donations.php @@ -776,18 +776,6 @@ function ( $item ) { $is_wc ? \wc_get_page_permalink( 'checkout' ) : '' ); - $donation_metadata = [ - 'currency' => \get_woocommerce_currency(), - 'amount' => $donation_value, - 'product_id' => $product_id, - 'referer' => $referer, - ]; - - /** - * Action to fire for donate checkout modal. - */ - \do_action( 'newspack_blocks_donate_block_modal', $donation_metadata ); - // Redirect to checkout. \wp_safe_redirect( apply_filters( 'newspack_donation_checkout_url', $checkout_url, $donation_value, $donation_frequency ) ); exit; From d032d7ea13392502d346d66478d54a5e9bca669b Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Wed, 21 Aug 2024 11:50:56 -0700 Subject: [PATCH 192/243] fix: correct linting error --- includes/reader-activation/class-reader-activation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index 46a22be0d9..2b75e9e29c 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -1475,7 +1475,7 @@ public static function newsletters_signup() { return new \WP_Error( 'no_lists_selected', __( 'No lists selected.', 'newspack-plugin' ) ); } - $result = \Newspack_Newsletters_Subscription::add_contact( + $result = \Newspack_Newsletters_Contacts::subscribe( [ 'email' => $email_address, 'metadata' => [ From 72faf82021369a544d51ad791f378044f76d7fe6 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Mon, 26 Aug 2024 09:53:21 -0400 Subject: [PATCH 193/243] feat(ras-acc): handle checkout redirect params (#3343) --- includes/class-magic-link.php | 33 ++++--- .../wc-memberships/class-memberships.php | 2 +- .../class-reader-activation.php | 7 +- src/reader-activation-auth/auth-form.js | 15 +++- src/reader-activation/checkout.js | 89 +++++++++++++++++++ src/reader-activation/index.js | 27 ++---- 6 files changed, 136 insertions(+), 37 deletions(-) create mode 100644 src/reader-activation/checkout.js diff --git a/includes/class-magic-link.php b/includes/class-magic-link.php index 4e59f26359..720af09c4d 100644 --- a/includes/class-magic-link.php +++ b/includes/class-magic-link.php @@ -34,6 +34,16 @@ final class Magic_Link { const OTP_MAX_ATTEMPTS = 5; const OTP_AUTH_ACTION = 'np_otp_auth'; const OTP_HASH_COOKIE = 'np_otp_hash'; + const ACCEPTED_PARAMS = [ + 'newspack_modal_checkout', + 'type', + 'layout', + 'frequency', + 'amount', + 'other', + 'product_id', + 'variation_id', + ]; /** * Current session secret. @@ -450,8 +460,7 @@ public static function send_email( $user, $redirect_to = '', $use_otp = true ) { if ( is_wp_error( $key ) ) { return $key; } - - $url = \add_query_arg( + $url = \add_query_arg( [ 'action' => self::AUTH_ACTION, 'email' => urlencode( $user->user_email ), @@ -469,7 +478,6 @@ public static function send_email( $user, $redirect_to = '', $use_otp = true ) { 'template' => '*SET_PASSWORD_LINK*', 'value' => Emails::get_password_reset_url( $user, $key ), ], - ]; if ( $use_otp && ! empty( $token_data['otp'] ) ) { $email_type = 'OTP_AUTH'; @@ -759,18 +767,21 @@ function () { $authenticated = self::authenticate( $user->ID, $token ); } - $redirect = \wp_validate_redirect( + $query_args = [ self::AUTH_ACTION_RESULT => true === $authenticated ? '1' : '0' ]; + foreach ( self::ACCEPTED_PARAMS as $param ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended - \sanitize_text_field( \wp_unslash( $_GET['redirect'] ?? '' ) ), + if ( isset( $_GET[ $param ] ) ) { + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $query_args[ $param ] = \sanitize_text_field( \wp_unslash( $_GET[ $param ] ) ); + } + } + $redirect = \sanitize_url( \wp_unslash( $_GET['redirect'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $redirect = \wp_validate_redirect( + \add_query_arg( $query_args, $redirect ), \remove_query_arg( [ 'action', 'email', 'token' ] ) ); - \wp_safe_redirect( - \add_query_arg( - [ self::AUTH_ACTION_RESULT => true === $authenticated ? '1' : '0' ], - $redirect - ) - ); + \wp_safe_redirect( $redirect ); exit; } diff --git a/includes/plugins/wc-memberships/class-memberships.php b/includes/plugins/wc-memberships/class-memberships.php index 2a3e2f51e9..8985be9ec2 100644 --- a/includes/plugins/wc-memberships/class-memberships.php +++ b/includes/plugins/wc-memberships/class-memberships.php @@ -726,7 +726,7 @@ public static function render_js() { window.newspackRAS = window.newspackRAS || []; window.newspackRAS.push( function( ras ) { ras.on( 'reader', function( ev ) { - if ( ev.detail.authenticated && ! window?.newspackReaderActivation?.getCheckoutStatus() ) { + if ( ev.detail.authenticated && ! window?.newspackReaderActivation?.isPendingCheckout() ) { if ( ras.overlays.get().length ) { ras.on( 'overlay', function( ev ) { if ( ! ev.detail.overlays.length ) { diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index 2b75e9e29c..a6cc82884b 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -1697,12 +1697,15 @@ public static function process_auth_form() { $password = isset( $_POST['password'] ) ? \sanitize_text_field( $_POST['password'] ) : ''; $lists = isset( $_POST['lists'] ) ? array_map( 'sanitize_text_field', $_POST['lists'] ) : []; $honeypot = isset( $_POST['email'] ) ? \sanitize_text_field( $_POST['email'] ) : ''; + $redirect_url = isset( $_POST['redirect_url'] ) ? \esc_url_raw( $_POST['redirect_url'] ) : ''; // phpcs:enable if ( ! empty( $current_page_url['path'] ) ) { $current_page_url = \esc_url( \home_url( $current_page_url['path'] ) ); } + $redirect = ! empty( $redirect_url ) ? $redirect_url : $current_page_url; + // Honeypot trap. if ( ! empty( $honeypot ) ) { return self::send_auth_form_response( @@ -1750,7 +1753,7 @@ public static function process_auth_form() { return self::send_auth_form_response( $payload, false ); } if ( self::is_reader_without_password( $user ) ) { - $sent = Magic_Link::send_email( $user, $current_page_url ); + $sent = Magic_Link::send_email( $user, $redirect ); if ( true !== $sent ) { return self::send_auth_form_response( new \WP_Error( 'unauthorized', \is_wp_error( $sent ) ? $sent->get_error_message() : __( 'We encountered an error sending an authentication link. Please try again.', 'newspack-plugin' ) ) ); } @@ -1772,7 +1775,7 @@ public static function process_auth_form() { $payload['authenticated'] = \is_wp_error( $authenticated ) ? 0 : 1; return self::send_auth_form_response( $payload, false ); case 'link': - $sent = Magic_Link::send_email( $user, $current_page_url ); + $sent = Magic_Link::send_email( $user, $redirect ); if ( true !== $sent ) { return self::send_auth_form_response( new \WP_Error( 'unauthorized', \is_wp_error( $sent ) ? $sent->get_error_message() : __( 'We encountered an error sending an authentication link. Please try again.', 'newspack-plugin' ) ) ); } diff --git a/src/reader-activation-auth/auth-form.js b/src/reader-activation-auth/auth-form.js index 66bbc0f4d1..b766d59092 100644 --- a/src/reader-activation-auth/auth-form.js +++ b/src/reader-activation-auth/auth-form.js @@ -4,6 +4,7 @@ * Internal dependencies. */ import { domReady, formatTime } from '../utils'; +import { getCheckoutRedirectUrl } from '../reader-activation/checkout'; import { openNewslettersSignupModal } from '../reader-activation-newsletters/newsletters-modal'; import './google-oauth'; @@ -157,6 +158,12 @@ window.newspackRAS.push( function ( readerActivation ) { body.set( 'reader-activation-auth-form', 1 ); body.set( 'npe', emailInput.value ); body.set( 'action', 'link' ); + if ( readerActivation.isPendingCheckout() ) { + const redirectUrl = getCheckoutRedirectUrl(); + if ( redirectUrl ) { + body.set( 'redirect_url', redirectUrl ); + } + } readerActivation .getCaptchaV3Token() // Get a token for reCAPTCHA v3, if needed. .then( captchaToken => { @@ -240,7 +247,7 @@ window.newspackRAS.push( function ( readerActivation ) { if ( container.authCallback && data?.registered && - ! readerActivation.getCheckoutStatus() + ! readerActivation.isPendingCheckout() ) { callback = ( authMessage, authData ) => openNewslettersSignupModal( { @@ -382,6 +389,12 @@ window.newspackRAS.push( function ( readerActivation ) { if ( ! body.has( 'npe' ) || ! body.get( 'npe' ) ) { return form.endLoginFlow( newspack_reader_activation_labels.invalid_email, 400 ); } + if ( readerActivation.isPendingCheckout() ) { + const redirectUrl = getCheckoutRedirectUrl(); + if ( redirectUrl ) { + body.set( 'redirect_url', redirectUrl ); + } + } if ( 'otp' === action ) { readerActivation .authenticateOTP( body.get( 'otp_code' ) ) diff --git a/src/reader-activation/checkout.js b/src/reader-activation/checkout.js new file mode 100644 index 0000000000..95995a2360 --- /dev/null +++ b/src/reader-activation/checkout.js @@ -0,0 +1,89 @@ +import { EVENTS, emit } from './events.js'; + +import { getReader } from './index.js'; +import Store from './store.js'; + +/** + * Reader Activation Library. + */ +export const store = Store(); + +/** + * Get the current checkout. + * + * @return {Object} Checkout data. + */ +export function getCheckout() { + return store.get( 'checkout' ) || {}; +} + +/** + * Set the current checkout data. + * + * @param {Object} data Checkout data. Optional. + * If empty or not provided, the checkout data will be cleared. + */ +export function setCheckoutData( data = {} ) { + store.set( 'checkout', data, false ); + emit( EVENTS.reader, getReader() ); +} + +/** + * Get the reader checkout data. + * + * @param {string} key Checkout data key. Optional. + * + * @return {any} Reader checkout data. + */ +export function getCheckoutData( key ) { + const checkout = getCheckout(); + if ( ! key ) { + return checkout; + } + return checkout?.[ key ]; +} + +/** + * Whether checkout is pending. + * + * @return {boolean} Whether checkout is pending. + */ +export function isPendingCheckout() { + return getCheckoutData( 'is_pending_checkout' ); +} + +/** + * Reset the reader checkout data. + */ +export function resetCheckoutData() { + setCheckoutData(); +} + +/** + * Get a checkout redirect URL. + * + * @return {string} A checkout redirect URL if checkout data is present. + * Otherwise, an empty string + */ +export function getCheckoutRedirectUrl() { + const checkoutType = getCheckoutData( 'type' ); + if ( ! checkoutType ) { + return ''; + } + const redirectUrl = new URL( window.location.href ); + redirectUrl.searchParams.set( 'newspack_modal_checkout', 1 ); + redirectUrl.searchParams.set( 'type', checkoutType ); + // Add checkout button params. + if ( checkoutType === 'checkout_button' ) { + redirectUrl.searchParams.set( 'product_id', getCheckoutData( 'product_id' ) ?? '' ); + redirectUrl.searchParams.set( 'variation_id', getCheckoutData( 'variation_id' ) ?? '' ); + } + // Add donate params. + if ( checkoutType === 'donate' ) { + redirectUrl.searchParams.set( 'layout', getCheckoutData( 'layout' ) ?? '' ); + redirectUrl.searchParams.set( 'frequency', getCheckoutData( 'frequency' ?? '' ) ); + redirectUrl.searchParams.set( 'amount', getCheckoutData( 'amount' ) ?? '' ); + redirectUrl.searchParams.set( 'other', getCheckoutData( 'other' ) ?? '' ); + } + return redirectUrl.href; +} diff --git a/src/reader-activation/index.js b/src/reader-activation/index.js index 015bf9f190..92ce9e244a 100644 --- a/src/reader-activation/index.js +++ b/src/reader-activation/index.js @@ -3,6 +3,7 @@ window.newspack_ras_config = window.newspack_ras_config || {}; import Store from './store.js'; +import { isPendingCheckout, setCheckoutData, getCheckoutData, resetCheckoutData } from './checkout.js'; import { EVENTS, on, off, emit } from './events.js'; import { getCookie, setCookie, generateID } from './utils.js'; import overlays from './overlays.js'; @@ -328,26 +329,6 @@ export function getAuthStrategy() { } return getCookie( 'np_auth_strategy' ); } -/** - * Set the reader checkout status. - * - * @param {boolean} status Checkout status. Default is false. - * - * @return {void} - */ -export function setCheckoutStatus( status = false ) { - setCookie( 'np_auth_checkout_status', status ); - emit( EVENTS.reader, getReader() ); - return status; -} -/** - * Get the reader checkout status. - * - * @return {boolean} Reader checkout status. - */ -export function getCheckoutStatus() { - return 'true' === getCookie( 'np_auth_checkout_status' ); -} /** * Ensure the client ID cookie is set. @@ -446,8 +427,10 @@ const readerActivation = { authenticateOTP, setAuthStrategy, getAuthStrategy, - setCheckoutStatus, - getCheckoutStatus, + setCheckoutData, + getCheckoutData, + isPendingCheckout, + resetCheckoutData, getCaptchaV3Token: window.newspack_grecaptcha ? window.newspack_grecaptcha?.getCaptchaV3Token : () => new Promise( res => res( '' ) ), // Empty promise. From 2ffc5e2f9c90def7226829a4bee107b52eac7b18 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Mon, 26 Aug 2024 13:19:46 -0700 Subject: [PATCH 194/243] fix: don't close modal when redirecting --- src/reader-activation-newsletters/newsletters-modal.js | 4 +++- src/reader-activation/index.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/reader-activation-newsletters/newsletters-modal.js b/src/reader-activation-newsletters/newsletters-modal.js index 657446925c..b6008bb4a0 100644 --- a/src/reader-activation-newsletters/newsletters-modal.js +++ b/src/reader-activation-newsletters/newsletters-modal.js @@ -65,7 +65,9 @@ export function openNewslettersSignupModal( config = {} ) { container.config = config; container.newslettersSignupCallback = ( message, data ) => { - close(); + if ( ! config?.skipClose ) { + close(); + } if ( config?.callback ) { config.callback( message, data ); } diff --git a/src/reader-activation/index.js b/src/reader-activation/index.js index 92ce9e244a..b24545c216 100644 --- a/src/reader-activation/index.js +++ b/src/reader-activation/index.js @@ -159,6 +159,7 @@ export function openAuthModal( config = {} ) { }, content: null, trigger: null, + skipClose: false, }, ...config, }; From 4ec56a97e5ccca5899743a7123f4403b4c2cf897 Mon Sep 17 00:00:00 2001 From: Laurel Fulford Date: Tue, 27 Aug 2024 12:39:38 -0700 Subject: [PATCH 195/243] fix: improve variable naming for clarity --- src/reader-activation-newsletters/newsletters-modal.js | 2 +- src/reader-activation/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reader-activation-newsletters/newsletters-modal.js b/src/reader-activation-newsletters/newsletters-modal.js index b6008bb4a0..ed68a4df56 100644 --- a/src/reader-activation-newsletters/newsletters-modal.js +++ b/src/reader-activation-newsletters/newsletters-modal.js @@ -65,7 +65,7 @@ export function openNewslettersSignupModal( config = {} ) { container.config = config; container.newslettersSignupCallback = ( message, data ) => { - if ( ! config?.skipClose ) { + if ( config?.closeOnSuccess ) { close(); } if ( config?.callback ) { diff --git a/src/reader-activation/index.js b/src/reader-activation/index.js index b24545c216..ddb0ef1986 100644 --- a/src/reader-activation/index.js +++ b/src/reader-activation/index.js @@ -159,7 +159,7 @@ export function openAuthModal( config = {} ) { }, content: null, trigger: null, - skipClose: false, + closeOnSuccess: true, }, ...config, }; From 824e885301f679465e85c3109ab7e0256061a202 Mon Sep 17 00:00:00 2001 From: Derrick Koo Date: Tue, 27 Aug 2024 14:25:51 -0600 Subject: [PATCH 196/243] fix(ras-acc): reCAPTCHA v2 + v3 for RAS-ACC flows (#3283) This PR (along with Automattic/newspack-blocks#1811 and Automattic/newspack-newsletters#1581) fixes reCAPTCHA v2 and v3 integrations for RAS-ACC flows, which are currently broken in epic/ras-acc. It also implements some improvements and standardizations to the reCAPTCHA implementations --- includes/class-recaptcha.php | 151 ++++-------- .../class-reader-activation.php | 8 +- src/blocks/reader-registration/index.php | 7 +- src/blocks/reader-registration/view.js | 52 ++-- src/other-scripts/recaptcha/index.js | 233 +++++++++++++----- src/reader-activation-auth/auth-form.js | 205 +++++++-------- src/reader-activation/index.js | 28 +-- .../connections/views/main/recaptcha.js | 60 +++-- 8 files changed, 368 insertions(+), 376 deletions(-) diff --git a/includes/class-recaptcha.php b/includes/class-recaptcha.php index 3e511feb44..309f429674 100644 --- a/includes/class-recaptcha.php +++ b/includes/class-recaptcha.php @@ -7,8 +7,6 @@ namespace Newspack; -use Error; - defined( 'ABSPATH' ) || exit; /** @@ -26,11 +24,6 @@ final class Recaptcha { public static function init() { \add_action( 'rest_api_init', [ __CLASS__, 'register_api_endpoints' ] ); \add_action( 'wp_enqueue_scripts', [ __CLASS__, 'register_scripts' ] ); - \add_action( 'newspack_newsletters_subscribe_block_before_email_field', [ __CLASS__, 'render_recaptcha_v2_container' ] ); - - // Add reCAPTCHA to the Woo checkout form. - \add_action( 'woocommerce_review_order_before_submit', [ __CLASS__, 'add_recaptcha_v2_to_checkout' ] ); - \add_action( 'woocommerce_checkout_after_customer_details', [ __CLASS__, 'add_recaptcha_v3_to_checkout' ] ); // Verify reCAPTCHA on checkout submission. \add_action( 'woocommerce_checkout_process', [ __CLASS__, 'verify_recaptcha_on_checkout' ] ); @@ -111,17 +104,14 @@ public static function get_script_url() { * Register the reCAPTCHA script. */ public static function register_scripts() { - // Styles only apply to the visible v2 widgets. - if ( self::can_use_captcha( 'v2' ) ) { + if ( self::can_use_captcha() ) { \wp_enqueue_style( self::SCRIPT_HANDLE, Newspack::plugin_url() . '/dist/other-scripts/recaptcha.css', [], NEWSPACK_PLUGIN_VERSION ); - } - if ( self::can_use_captcha() ) { // Enqueue the reCAPTCHA API from Google's servers. // Note: version arg Must be null to avoid the &ver param being read as part of the reCAPTCHA site key. \wp_register_script( @@ -131,8 +121,6 @@ public static function register_scripts() { null, // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion false ); - \wp_script_add_data( self::SCRIPT_HANDLE_API, 'async', true ); - \wp_script_add_data( self::SCRIPT_HANDLE_API, 'defer', true ); \wp_enqueue_script( self::SCRIPT_HANDLE, @@ -141,8 +129,6 @@ public static function register_scripts() { NEWSPACK_PLUGIN_VERSION, true ); - \wp_script_add_data( self::SCRIPT_HANDLE, 'async', true ); - \wp_script_add_data( self::SCRIPT_HANDLE, 'defer', true ); \wp_localize_script( self::SCRIPT_HANDLE, @@ -182,8 +168,7 @@ public static function api_permissions_check() { public static function get_settings_config() { return [ 'use_captcha' => false, - 'site_key' => '', - 'site_secret' => '', + 'credentials' => [], 'threshold' => 0.5, 'version' => 'v3', ]; @@ -206,7 +191,19 @@ public static function api_get_settings() { * @return WP_REST_Response containing the settings list. */ public static function api_update_settings( $request ) { - return \rest_ensure_response( self::update_settings( $request->get_params() ) ); + $params = $request->get_params(); + if ( isset( $params['site_key'] ) || isset( $params['site_secret'] ) ) { + $version = $params['version'] ?? self::get_setting( 'version' ); + $credentials = self::get_setting( 'credentials' ); + if ( isset( $params['site_key'] ) ) { + $credentials[ $version ]['site_key'] = $params['site_key']; + } + if ( isset( $params['site_secret'] ) ) { + $credentials[ $version ]['site_secret'] = $params['site_secret']; + } + $params['credentials'] = $credentials; + } + return \rest_ensure_response( self::update_settings( $params ) ); } /** @@ -221,22 +218,32 @@ public static function get_settings() { $settings[ $key ] = self::get_setting( $key ); } - // Migrate reCAPTCHA settings from Stripe wizard, for more generalized usage. - if ( ! $settings['use_captcha'] && empty( $settings['site_key'] ) && empty( $settings['site_secret'] ) ) { - $stripe_settings = Stripe_Connection::get_stripe_data(); - if ( ! empty( $stripe_settings['useCaptcha'] ) && ! empty( $stripe_settings['captchaSiteKey'] ) && ! empty( $stripe_settings['captchaSiteSecret'] ) ) { - // If we have all of the required settings in Stripe settings, migrate them here. - self::update_settings( - [ - 'use_captcha' => $stripe_settings['useCaptcha'], - 'site_key' => $stripe_settings['captchaSiteKey'], - 'site_secret' => $stripe_settings['captchaSiteSecret'], - ] - ); - - $settings['use_captcha'] = $stripe_settings['useCaptcha']; - $settings['site_key'] = $stripe_settings['captchaSiteKey']; - $settings['site_secret'] = $stripe_settings['captchaSiteSecret']; + // Migrate reCAPTCHA settings from separate site_key/site_secret options to credentials array. + $current_version = $settings['version']; + if ( + $settings['use_captcha'] && + ( + empty( $settings['credentials'][ $current_version ]['site_key'] ) || + empty( $settings['credentials'][ $current_version ]['site_secret'] ) + ) + ) { + $legacy_key = \get_option( self::OPTIONS_PREFIX . 'site_key', false ); + $legacy_secret = \get_option( self::OPTIONS_PREFIX . 'site_secret', false ); + + if ( ! empty( $legacy_key ) ) { + $settings['credentials'][ $current_version ]['site_key'] = $legacy_key; + } + if ( ! empty( $legacy_secret ) ) { + $settings['credentials'][ $current_version ]['site_secret'] = $legacy_secret; + } + + // Avoid notoptions cache issue. + wp_cache_delete( 'notoptions', 'options' ); + wp_cache_delete( 'alloptions', 'options' ); + $updated = \update_option( self::OPTIONS_PREFIX . 'credentials', $settings['credentials'] ); + if ( $updated ) { + \delete_option( self::OPTIONS_PREFIX . 'site_key' ); + \delete_option( self::OPTIONS_PREFIX . 'site_secret' ); } } @@ -272,14 +279,18 @@ public static function get_setting( $key ) { * Get the reCAPTCHA site key. */ public static function get_site_key() { - return self::get_setting( 'site_key' ); + $version = self::get_setting( 'version' ); + $credentials = self::get_setting( 'credentials' ); + return $credentials[ $version ]['site_key'] ?? ''; } /** * Get the reCAPTCHA site secret. */ public static function get_site_secret() { - return self::get_setting( 'site_secret' ); + $version = self::get_setting( 'version' ); + $credentials = self::get_setting( 'credentials' ); + return $credentials[ $version ]['site_secret'] ?? ''; } /** @@ -408,78 +419,12 @@ public static function verify_captcha() { return true; } - /** - * Render a container for the reCAPTCHA v2 checkbox widget. - */ - public static function render_recaptcha_v2_container() { - if ( ! self::can_use_captcha( 'v2' ) ) { - return; - } - ?> -
- - - - __( 'Signup successful!', 'newspack-plugin' ), 'newsletters_title' => __( 'Sign up for newsletters', 'newspack-plugin' ), + 'auth_form_action' => self::AUTH_FORM_ACTION, ]; /** @@ -1256,7 +1257,7 @@ public static function render_auth_form( $in_modal = true ) {

-
+
@@ -1282,9 +1283,6 @@ public static function render_auth_form( $in_modal = true ) {

- - -
@@ -1717,7 +1715,7 @@ public static function process_auth_form() { } // reCAPTCHA test on account registration only. - if ( 'register' === $action && Recaptcha::can_use_captcha() ) { + if ( 'register' === $action && Recaptcha::can_use_captcha( 'v3' ) ) { $captcha_result = Recaptcha::verify_captcha(); if ( \is_wp_error( $captcha_result ) ) { return self::send_auth_form_response( $captcha_result ); diff --git a/src/blocks/reader-registration/index.php b/src/blocks/reader-registration/index.php index 543f834cd6..2c6c7d0fef 100644 --- a/src/blocks/reader-registration/index.php +++ b/src/blocks/reader-registration/index.php @@ -205,7 +205,7 @@ function render_block( $attrs, $content ) {
- +