Skip to content

Commit

Permalink
Newsletter categories: Render non-interactive newsletter category pil…
Browse files Browse the repository at this point in the history
…ls in the editor (#32666)

* [not verified] Add newsletter categories to subscription block

Added a new feature to the subscription block which displays newsletter categories. The added categories are styled and displayed above the subscription form. Also added a new hook to query newsletter categories from the backend. This feature enhances user experience by offering categorized subscribing options. The form width is reduced when categories are displayed for better aesthetics.

* [not verified] Add newsletter categories to subscription block

Added a new feature to the subscription block which displays newsletter categories. The added categories are styled and displayed above the subscription form. Also added a new hook to query newsletter categories from the backend. This feature enhances user experience by offering categorized subscribing options. The form width is reduced when categories are displayed for better aesthetics.

* [not verified] Add 'enabled' state to newsletter category hooks

The changes introduced a new 'enabled' state to the useNewsletterCategories hook. This was done to allow better manipulation of the subscription blocks based on whether the newsletter category function is enabled by the user or not, hence improving user experience when interacting with subscription blocks.

* [not verified] Remove unnecessary spacing in view.scss

This commit removes the additional two lines of spacing at the beginning of the view.scss file within the subscriptions block. This was done to clean the code and make it adhering to the standard coding practices, which enhances the readability and maintainability.

* [not verified] Add newsletter categories REST API endpoint and adjust client-side fetch

This commit introduces a new REST API endpoint for retrieving the newsletter categories. The new endpoint will enable a more seamless and effective integration of these categories in the client-side.

Moreover, modifications were also made to the 'trait-wpcom-rest-api-proxy-request-trait.php' file. Now the body for Client::wpcom_json_api_request_as_user is checked if not null. This was done to prevent an error when the body is null.

Lastly, the fetch request at 'use-newsletter-categories.js' has been updated to use the new /newsletter-categories endpoint within the local server environment instead of making a direct request to the public API.

* [not verified] Update styling & endpoint

* [not verified] Add newsletter categories mock function for testing

In the subscriptions module, a mock function was added in the test/edit.js file. This was done to simulate the behavior of the actual 'useNewsletterCategories' function in the unit tests. This will facilitate the testing process by controlling its response and help in improving the code coverage.

* - Better usage of CSS variables
- Renamed --border-radius to --subscribe-block-border-radius
- Removed check of WPCOM

---------

Co-authored-by: Jeremy Herve <[email protected]>
  • Loading branch information
TimBroddin and jeherve authored Sep 7, 2023
1 parent feaae2d commit 4f5da6a
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* REST API endpoint for the Newsletter Categories
*
* @package automattic/jetpack
* @since $$next-version$$
*/

use Automattic\Jetpack\Status\Host;

require_once __DIR__ . '/trait-wpcom-rest-api-proxy-request-trait.php';

/**
* Class WPCOM_REST_API_V2_Endpoint_Following
*/
class WPCOM_REST_API_V2_Endpoint_Newsletter_Categories_List extends WP_REST_Controller {
use WPCOM_REST_API_Proxy_Request_Trait;

/**
* Constructor.
*/
public function __construct() {
$this->wpcom_is_wpcom_only_endpoint = true;
$this->wpcom_is_site_specific_endpoint = true;
$this->base_api_path = 'wpcom';
$this->version = 'v2';
$this->namespace = $this->base_api_path . '/' . $this->version;
$this->rest_base = '/newsletter-categories';
$this->wpcom_is_wpcom_only_endpoint = true;
$this->wpcom_is_site_specific_endpoint = true;

add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}

/**
* Register routes.
*/
public function register_routes() {
$options = array(
'show_in_index' => true,
'methods' => 'GET',
// if this is not a wpcom site, we need to proxy the request to wpcom
'callback' => ( ( new Host() )->is_wpcom_simple() ) ? array(
$this,
'get_newsletter_categories',
) : array( $this, 'proxy_request_to_wpcom_as_user' ),
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
);

register_rest_route(
$this->namespace,
$this->rest_base,
$options
);
}

/**
* Gets the site's newsletter categories
*
* @return array|WP_Error list of newsletter categories
*/
public function get_newsletter_categories() {
require_lib( 'newsletter-categories' );

$newsletter_categories = get_newsletter_categories();

// Include subscription counts for each category if the user can manage categories.
if ( $this->can_manage_categories() === true ) {
$subscription_counts_per_category = get_blog_subscription_counts_per_category();
array_walk(
$newsletter_categories,
function ( &$category ) use ( $subscription_counts_per_category ) {
$category['subscription_count'] = $subscription_counts_per_category[ $category['id'] ] ? $subscription_counts_per_category[ $category['id'] ] : 0;
}
);
}

return rest_ensure_response(
array(
'enabled' => (bool) get_option( 'wpcom_newsletter_categories_enabled', false ),
'newsletter_categories' => $newsletter_categories,
)
);
}
}

wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_Newsletter_Categories_List' );
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ public function proxy_request_to_wpcom_as_user( $request, $path = '' ) {
'method' => $request->get_method(),
);

$response = Client::wpcom_json_api_request_as_user( $api_url, $this->version, $request_options, $request->get_body(), $this->base_api_path );
// If no body is present, passing it as $request->get_body() will cause an error.
$body = $request->get_body() ? $request->get_body() : null;

$response = Client::wpcom_json_api_request_as_user( $api_url, $this->version, $request_options, $body, $this->base_api_path );

if ( is_wp_error( $response ) ) {
return $response;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: enhancement

Adds support for newsletter categories
28 changes: 27 additions & 1 deletion projects/plugins/jetpack/extensions/blocks/subscriptions/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
DEFAULT_FONTSIZE_VALUE,
} from './constants';
import SubscriptionControls from './controls';
import { useNewsletterCategories } from './hooks/use-newsletter-categories';
import { SubscriptionsPlaceholder } from './subscription-placeholder';
import SubscriptionSkeletonLoader from './subscription-skeleton-loader';
import { name } from './';
Expand Down Expand Up @@ -116,6 +117,9 @@ export function SubscriptionEdit( props ) {
};
} );

const { data: newsletterCategories, enabled: newsletterCategoriesEnabled } =
useNewsletterCategories();

const emailFieldGradient = isGradientAvailable
? useGradient( {
gradientAttribute: 'emailFieldGradient',
Expand Down Expand Up @@ -179,6 +183,12 @@ export function SubscriptionEdit( props ) {
padding: getPaddingStyleValue( padding ),
};

const cssVars = {
'--subscribe-block-border-radius': borderRadius
? borderRadius + 'px'
: DEFAULT_BORDER_RADIUS_VALUE + 'px',
};

const emailFieldStyles = {
...sharedStyles,
...( ! emailFieldBackgroundColor.color && emailFieldGradient.gradientValue
Expand All @@ -202,6 +212,9 @@ export function SubscriptionEdit( props ) {
className,
'wp-block-jetpack-subscriptions__container',
'wp-block-jetpack-subscriptions__supports-newline',
newsletterCategoriesEnabled
? 'wp-block-jetpack-subscriptions__newsletter-categories-enabled'
: undefined,
buttonOnNewLine ? 'wp-block-jetpack-subscriptions__use-newline' : undefined,
showSubscribersTotal ? 'wp-block-jetpack-subscriptions__show-subs' : undefined
);
Expand Down Expand Up @@ -279,7 +292,20 @@ export function SubscriptionEdit( props ) {
</BlockControls>
) }

<div className={ getBlockClassName() }>
<div className={ getBlockClassName() } style={ cssVars }>
<div className="wp-block-jetpack-subscriptions__newsletter-categories">
{ newsletterCategories.map( category => {
return (
<div
key={ `newsletter-category-${ category.id }` }
className="wp-block-jetpack-subscriptions__newsletter-category"
>
{ category.name }
</div>
);
} ) }
</div>

<div className="wp-block-jetpack-subscriptions__form" role="form">
<TextControl
placeholder={ subscribePlaceholder }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import apiFetch from '@wordpress/api-fetch';
import { useEffect, useState } from '@wordpress/element';

const useNewsletterCategories = () => {
const [ data, setData ] = useState( [] );
const [ enabled, setEnabled ] = useState( false );
const [ error, setError ] = useState( false );
const [ loading, setLoading ] = useState( true );

useEffect( () => {
const fetchData = async () => {
try {
const newsLetterCategories = await apiFetch( {
path: `/wpcom/v2/newsletter-categories`,
} );
setData( newsLetterCategories?.newsletter_categories );
setEnabled( newsLetterCategories?.enabled ?? false );
} catch ( e ) {
setError( true );
} finally {
setLoading( false );
}
};

fetchData();
}, [] );

return { data, enabled, error, loading };
};

export { useNewsletterCategories };
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,20 @@ jest.mock( '@wordpress/element', () => ( {

jest.mock( '@wordpress/notices', () => {}, { virtual: true } );

jest.mock( '../hooks/use-newsletter-categories', () => ( {
useNewsletterCategories: () => {
return {
data: [],
enabled: false,
error: false,
loading: false,
};
},
} ) );

describe( 'SubscriptionEdit', () => {
test( 'adds correct classes to container', async () => {
const { container } = render( <SubscriptionEdit { ...defaultProps } /> );

// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
expect( container.querySelector( `.${ defaultProps.className }` ) ).toBeInTheDocument();
} );
Expand Down
31 changes: 31 additions & 0 deletions projects/plugins/jetpack/extensions/blocks/subscriptions/view.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import '@automattic/jetpack-base-styles/gutenberg-base-styles';

.is-style-compact {
.wp-block-jetpack-subscriptions__button,
.wp-block-button__link {
Expand Down Expand Up @@ -96,3 +98,32 @@
}
}
}

.wp-block-jetpack-subscriptions__newsletter-categories {
margin-top: 8px;
margin-bottom: 24px;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 8px;

.wp-block-jetpack-subscriptions__newsletter-category {
padding: 6px 10px;
font-family: $default-font;
font-size: $default-font-size;
font-weight: 500;
line-height: 20px;
color: $gray-600;
border: 1px solid $gray-200;
border-radius: var(--subscribe-block-border-radius);
}
}

// make the form less wide when there are categories
.wp-block-jetpack-subscriptions__newsletter-categories-enabled {
.wp-block-jetpack-subscriptions__form {
width: 80%;
margin-left: auto;
margin-right: auto;
}
}

0 comments on commit 4f5da6a

Please sign in to comment.