Skip to content

Commit

Permalink
Merge branch 'master' into epic/ras-acc
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelpeixe committed Dec 20, 2023
2 parents 5b47c04 + a0040b4 commit 1c6abaa
Show file tree
Hide file tree
Showing 11 changed files with 345 additions and 136 deletions.
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
# [2.4.0](https://github.com/Automattic/newspack-blocks/compare/v2.3.0...v2.4.0) (2023-12-11)


### Bug Fixes

* modal checkout template markup ([#1608](https://github.com/Automattic/newspack-blocks/issues/1608)) ([4d593db](https://github.com/Automattic/newspack-blocks/commit/4d593db4e80b57570e13db2ed203586bab974fb6))
* **modal-checkout:** align Stripe's "save payment" checkbox ([#1623](https://github.com/Automattic/newspack-blocks/issues/1623)) ([69e0e42](https://github.com/Automattic/newspack-blocks/commit/69e0e42b3d6f6ab8b1a918346e0d2f8e90eeabcb))
* **modal-checkout:** prevent initial render of details table ([#1601](https://github.com/Automattic/newspack-blocks/issues/1601)) ([06d4ccd](https://github.com/Automattic/newspack-blocks/commit/06d4ccdc799cb4233a1a85efdbd1264399d85291))
* replace FILTER_SANITIZE_STRING ([6f805b0](https://github.com/Automattic/newspack-blocks/commit/6f805b0806d24f9e44d293a13ca486fdf23c73ab))


### Features

* improve performance of modal checkout ([#1607](https://github.com/Automattic/newspack-blocks/issues/1607)) ([a48d190](https://github.com/Automattic/newspack-blocks/commit/a48d19068cc0fc22d36f6371bdee447f72177ed7))
* **modal-checkout:** add filter to cart item data ([#1590](https://github.com/Automattic/newspack-blocks/issues/1590)) ([1e83dc1](https://github.com/Automattic/newspack-blocks/commit/1e83dc119aac531db18dbdcc7aaa4c781aa8576e))


### Performance Improvements

* **modal-checkout:** process checkout request earlier ([#1612](https://github.com/Automattic/newspack-blocks/issues/1612)) ([5c58f5e](https://github.com/Automattic/newspack-blocks/commit/5c58f5e811bb24098afb093c3a4efbb8efa83d4a))

# [2.4.0-alpha.1](https://github.com/Automattic/newspack-blocks/compare/v2.3.0...v2.4.0-alpha.1) (2023-12-07)


### Bug Fixes

* modal checkout template markup ([#1608](https://github.com/Automattic/newspack-blocks/issues/1608)) ([4d593db](https://github.com/Automattic/newspack-blocks/commit/4d593db4e80b57570e13db2ed203586bab974fb6))
* **modal-checkout:** align Stripe's "save payment" checkbox ([#1623](https://github.com/Automattic/newspack-blocks/issues/1623)) ([69e0e42](https://github.com/Automattic/newspack-blocks/commit/69e0e42b3d6f6ab8b1a918346e0d2f8e90eeabcb))
* **modal-checkout:** prevent initial render of details table ([#1601](https://github.com/Automattic/newspack-blocks/issues/1601)) ([06d4ccd](https://github.com/Automattic/newspack-blocks/commit/06d4ccdc799cb4233a1a85efdbd1264399d85291))
* replace FILTER_SANITIZE_STRING ([6f805b0](https://github.com/Automattic/newspack-blocks/commit/6f805b0806d24f9e44d293a13ca486fdf23c73ab))


### Features

* improve performance of modal checkout ([#1607](https://github.com/Automattic/newspack-blocks/issues/1607)) ([a48d190](https://github.com/Automattic/newspack-blocks/commit/a48d19068cc0fc22d36f6371bdee447f72177ed7))
* **modal-checkout:** add filter to cart item data ([#1590](https://github.com/Automattic/newspack-blocks/issues/1590)) ([1e83dc1](https://github.com/Automattic/newspack-blocks/commit/1e83dc119aac531db18dbdcc7aaa4c781aa8576e))


### Performance Improvements

* **modal-checkout:** process checkout request earlier ([#1612](https://github.com/Automattic/newspack-blocks/issues/1612)) ([5c58f5e](https://github.com/Automattic/newspack-blocks/commit/5c58f5e811bb24098afb093c3a4efbb8efa83d4a))

# [2.3.0](https://github.com/Automattic/newspack-blocks/compare/v2.2.4...v2.3.0) (2023-12-07)


Expand Down
48 changes: 48 additions & 0 deletions includes/class-modal-checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public static function init() {
add_action( 'woocommerce_checkout_before_terms_and_conditions', [ __CLASS__, 'render_before_terms_and_conditions' ] );
add_filter( 'woocommerce_enable_order_notes_field', [ __CLASS__, 'enable_order_notes_field' ] );

/** Custom handling for registered users. */
add_filter( 'woocommerce_checkout_customer_id', [ __CLASS__, 'associate_existing_user' ] );
add_filter( 'woocommerce_checkout_posted_data', [ __CLASS__, 'skip_account_creation' ], 11 );

// Remove some stuff from the modal checkout page. It's displayed in an iframe, so it should not be treated as a separate page.
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'dequeue_scripts' ], 11 );
add_filter( 'newspack_reader_activation_should_render_auth', [ __CLASS__, 'is_not_modal_checkout_filter' ] );
Expand Down Expand Up @@ -992,6 +996,50 @@ public static function enable_order_notes_field( $enable ) {
return $enable;
}

/**
* If a reader tries to make a purchase with an email address that
* has been previously registered, automatically associate the transaction
* with the user.
*
* @param int $customer_id Current customer ID.
*
* @return int Modified $customer_id
*/
public static function associate_existing_user( $customer_id ) {
if ( ! self::is_modal_checkout() ) {
return $customer_id;
}
$billing_email = filter_input( INPUT_POST, 'billing_email', FILTER_SANITIZE_EMAIL );
if ( $billing_email ) {
$customer = \get_user_by( 'email', $billing_email );
if ( $customer ) {
$customer_id = $customer->ID;
}
}
return $customer_id;
}

/**
* Don't force account registration/login on Woo purchases for existing users.
*
* @param array $data Array of Woo checkout data.
*
* @return array Modified $data.
*/
public static function skip_account_creation( $data ) {
if ( ! self::is_modal_checkout() ) {
return $data;
}
$email = $data['billing_email'];
$customer = \get_user_by( 'email', $email );
if ( $customer ) {
$data['createaccount'] = 0;
\add_filter( 'woocommerce_checkout_registration_required', '__return_false', 9999 );
}

return $data;
}

/**
* Filter the a value dependent on the page not being modal checkout.
*
Expand Down
4 changes: 2 additions & 2 deletions newspack-blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
* Author URI: https://newspack.com/
* Text Domain: newspack-blocks
* Domain Path: /languages
* Version: 2.3.0
* Version: 2.4.0
*
* @package Newspack_Blocks
*/

define( 'NEWSPACK_BLOCKS__PLUGIN_FILE', __FILE__ );
define( 'NEWSPACK_BLOCKS__BLOCKS_DIRECTORY', 'dist/' );
define( 'NEWSPACK_BLOCKS__PLUGIN_DIR', plugin_dir_path( NEWSPACK_BLOCKS__PLUGIN_FILE ) );
define( 'NEWSPACK_BLOCKS__VERSION', '2.3.0' );
define( 'NEWSPACK_BLOCKS__VERSION', '2.4.0' );

require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks.php';
require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks-api.php';
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@automattic/newspack-blocks",
"version": "2.3.0",
"version": "2.4.0",
"author": "Automattic",
"devDependencies": {
"@rushstack/eslint-patch": "^1.5.1",
Expand Down
32 changes: 26 additions & 6 deletions src/blocks/donate/edit/FrequencyBasedLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import classNames from 'classnames';
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useMemo, useEffect, useRef } from '@wordpress/element';
import { useMemo, useEffect, useRef, useState } from '@wordpress/element';
import { SelectControl } from '@wordpress/components';
import { RichText } from '@wordpress/block-editor';

Expand Down Expand Up @@ -68,29 +68,48 @@ const FrequencyBasedLayout = ( props: { isTiered: boolean } & ComponentProps ) =
const isRenderingStripePaymentForm =
window.newspack_blocks_data?.is_rendering_stripe_payment_form;

const [ selectedFrequency, setSelectedFrequency ] = useState( attributes.defaultFrequency );

const renderFrequencySelect = ( frequencySlug: DonationFrequencySlug ) => (
<>
<input
type="radio"
value={ frequencySlug }
id={ `newspack-donate-${ frequencySlug }-${ uid }` }
name="donation_frequency"
defaultChecked={ frequencySlug === attributes.defaultFrequency }
checked={ frequencySlug === selectedFrequency }
onChange={ evt => setSelectedFrequency( evt.target.value as 'once' | 'month' | 'year' ) }
/>
<label
htmlFor={ 'newspack-donate-' + frequencySlug + '-' + uid }
className="wpbnbd__button freq-label"
>
<label htmlFor={ 'newspack-donate-' + frequencySlug + '-' + uid }>
{ FREQUENCIES[ frequencySlug ] }
</label>
</>
);

const renderTab = ( frequencySlug: DonationFrequencySlug ) => (
<button
key={ frequencySlug }
role="tab"
className={ classNames( 'wpbnbd__button freq-label', {
'wpbnbd__button--active': frequencySlug === selectedFrequency,
} ) }
id={ `tab-newspack-donate-${ frequencySlug }-${ uid }` }
onClick={ evt => {
evt.preventDefault();
setSelectedFrequency( frequencySlug );
} }
>
{ FREQUENCIES[ frequencySlug ] }
</button>
);

// This code is fired on tab select and updates aria elements, tabindex states, and radio buttons
const displayAmount = ( amount: number ) => amount.toFixed( 2 ).replace( /\.?0*$/, '' );

const renderUntieredForm = () => (
<div className="wp-block-newspack-blocks-donate__options">
<div className="wp-block-newspack-blocks-donate__frequencies frequencies">
<div className="tab-container">{ availableFrequencies.map( renderTab ) }</div>
{ availableFrequencies.map( frequencySlug => (
<div
className="wp-block-newspack-blocks-donate__frequency frequency"
Expand Down Expand Up @@ -123,6 +142,7 @@ const FrequencyBasedLayout = ( props: { isTiered: boolean } & ComponentProps ) =
const renderTieredForm = () => (
<div className="wp-block-newspack-blocks-donate__options">
<div className="wp-block-newspack-blocks-donate__frequencies frequencies">
<div className="tab-container">{ availableFrequencies.map( renderTab ) }</div>
{ availableFrequencies.map( frequencySlug => (
<div
className="wp-block-newspack-blocks-donate__frequency frequency"
Expand Down
62 changes: 62 additions & 0 deletions src/blocks/donate/frequency-based/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,74 @@ const handleOtherValue = ( container: HTMLElement ) => {
} );
};

const addAccessibleTabs = ( container: HTMLElement ) => {
// Get the block's tabs, panels, and radio buttons associated with donation frequency.
const tabList = container.querySelectorAll(
'div[role="tablist"] [role="tab"]'
) as NodeListOf< HTMLElement >;
const panels = container.querySelectorAll( 'div[role="tabpanel"]' ) as NodeListOf< HTMLElement >;
const radioButtons = container.querySelectorAll(
'input[type="radio"][name="donation_frequency"]'
) as NodeListOf< HTMLInputElement >;
// Figure out which radio button is currently selected.
const checkedRadioId =
Array.from( radioButtons ).find( ( radio: HTMLInputElement ) => radio.checked )?.id || null;

// Set the tab associated to the radio button to selected.
if ( checkedRadioId ) {
const selectedTabId = `tab-${ checkedRadioId }`;
document.getElementById( selectedTabId )?.setAttribute( 'aria-selected', 'true' );
}

// Add a click event listener to each tab.
tabList.forEach( ( tab: HTMLElement ) => {
tab.addEventListener( 'click', function () {
selectTab( tab, tabList, radioButtons, panels );
} );
} );
};

const selectTab = (
tab: HTMLElement,
tabList: NodeListOf< HTMLElement >,
radioButtons: NodeListOf< HTMLInputElement >,
panels: NodeListOf< HTMLElement >
) => {
// Loop through tabs and set them as selected or not selected:
tabList.forEach( ( thisTab: HTMLElement ) => {
if ( tab === thisTab ) {
thisTab.setAttribute( 'aria-selected', 'true' );
thisTab.classList.add( 'wpbnbd__button--active' );
} else {
thisTab.setAttribute( 'aria-selected', 'false' );
thisTab.classList.remove( 'wpbnbd__button--active' );
}
} );

// Update the underlying radio button.
const tabId = tab.id || '';
const frequencyId = tabId.replace( 'tab-', '' );
radioButtons.forEach( ( radio: HTMLInputElement ) => {
radio.checked = frequencyId === radio.id;
} );

// Loop through the panels and set tabindex 0 on the selected panel; remove it from others.
panels.forEach( ( panel: HTMLElement ) => {
if ( tab.getAttribute( 'aria-controls' ) === panel.id ) {
panel.setAttribute( 'tabindex', '0' );
} else {
panel.removeAttribute( 'tabindex' );
}
} );
};

export const processFrequencyBasedElements = ( parentEl = document ) => {
const elements = parentEl.querySelectorAll(
'.wpbnbd--frequency-based'
) as NodeListOf< HTMLElement >;
elements.forEach( container => {
handleOtherValue( container );
addAccessibleTabs( container );
} );
};

Expand Down
Loading

0 comments on commit 1c6abaa

Please sign in to comment.