Skip to content

Commit c80ac11

Browse files
holdercpokmttdhr
authored andcommitted
Subscriptions: allow pre-selecting newsletter categories in block settings (#41567)
1 parent be865f0 commit c80ac11

File tree

10 files changed

+226
-18
lines changed

10 files changed

+226
-18
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: enhancement
3+
4+
Subscriptions: pre-select newsletter categories

projects/plugins/jetpack/extensions/blocks/subscriptions/block.json

+8
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@
115115
},
116116
"className": {
117117
"type": "string"
118+
},
119+
"preselectNewsletterCategories": {
120+
"type": "boolean",
121+
"default": false
122+
},
123+
"selectedNewsletterCategoryIds": {
124+
"type": "array",
125+
"default": []
118126
}
119127
},
120128
"example": {}

projects/plugins/jetpack/extensions/blocks/subscriptions/controls.js

+57-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import {
66
FontSizePicker,
77
__experimentalPanelColorGradientSettings as PanelColorGradientSettings, // eslint-disable-line @wordpress/no-unsafe-wp-apis
88
} from '@wordpress/block-editor';
9-
import { ToggleControl, PanelBody, RangeControl, TextareaControl } from '@wordpress/components';
9+
import {
10+
ToggleControl,
11+
PanelBody,
12+
RangeControl,
13+
TextareaControl,
14+
CheckboxControl,
15+
} from '@wordpress/components';
1016
import { createInterpolateElement } from '@wordpress/element';
1117
import { __, _n, sprintf } from '@wordpress/i18n';
1218
import InspectorNotice from '../../shared/components/inspector-notice';
@@ -30,6 +36,8 @@ import {
3036
} from './constants';
3137

3238
export default function SubscriptionControls( {
39+
availableNewsletterCategories,
40+
areNewsletterCategoriesEnabled,
3341
buttonBackgroundColor,
3442
borderColor,
3543
buttonGradient,
@@ -43,6 +51,8 @@ export default function SubscriptionControls( {
4351
includeSocialFollowers,
4452
isGradientAvailable,
4553
padding,
54+
preselectNewsletterCategories,
55+
selectedNewsletterCategoryIds,
4656
setAttributes,
4757
setBorderColor,
4858
setButtonBackgroundColor,
@@ -302,6 +312,52 @@ export default function SubscriptionControls( {
302312
onChange={ newSuccessMessage => setAttributes( { successMessage: newSuccessMessage } ) }
303313
/>
304314
) }
315+
{ areNewsletterCategoriesEnabled && availableNewsletterCategories.length > 0 && (
316+
<>
317+
<ToggleControl
318+
__nextHasNoMarginBottom={ true }
319+
label={ __( 'Pre-select categories', 'jetpack' ) }
320+
checked={ preselectNewsletterCategories }
321+
onChange={ value => {
322+
setAttributes( { preselectNewsletterCategories: value } );
323+
} }
324+
help={ __(
325+
'When enabled, the user will be automatically subscribed to the selected categories below when they submit the form.',
326+
'jetpack'
327+
) }
328+
/>
329+
{ preselectNewsletterCategories && (
330+
<fieldset>
331+
<legend className="wp-block-jetpack-subscriptions__legend">
332+
{ __( 'Categories', 'jetpack' ) }
333+
</legend>
334+
{ availableNewsletterCategories.map( category => (
335+
<CheckboxControl
336+
key={ category.id }
337+
__nextHasNoMarginBottom={ true }
338+
disabled={ ! preselectNewsletterCategories }
339+
label={ category.name }
340+
checked={ selectedNewsletterCategoryIds.includes( category.id ) }
341+
onChange={ () => {
342+
const selectedIds = selectedNewsletterCategoryIds.includes( category.id )
343+
? selectedNewsletterCategoryIds.filter( id => id !== category.id )
344+
: [ ...selectedNewsletterCategoryIds, category.id ];
345+
346+
const updates = { selectedNewsletterCategoryIds: selectedIds };
347+
348+
// If no categories are selected, disable the preselect option
349+
if ( selectedIds.length === 0 ) {
350+
updates.preselectNewsletterCategories = false;
351+
}
352+
353+
setAttributes( updates );
354+
} }
355+
/>
356+
) ) }
357+
</fieldset>
358+
) }
359+
</>
360+
) }
305361
</PanelBody>
306362
</>
307363
);

projects/plugins/jetpack/extensions/blocks/subscriptions/edit.js

+16
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { getActiveStyleName } from '../../shared/block-styles';
1919
import { getValidatedAttributes } from '../../shared/get-validated-attributes';
2020
import GetAddPaidPlanButton, { paidPlanButtonText } from '../../shared/memberships/utils';
2121
import './view.scss';
22+
import './editor.scss';
2223
import { store as membershipProductsStore } from '../../store/membership-products';
2324
import metadata from './block.json';
2425
import {
@@ -84,6 +85,8 @@ export function SubscriptionEdit( props ) {
8485
className,
8586
includeSocialFollowers,
8687
padding,
88+
preselectNewsletterCategories,
89+
selectedNewsletterCategoryIds,
8790
spacing,
8891
submitButtonText = DEFAULT_SUBMIT_BUTTON_LABEL,
8992
subscribePlaceholder = DEFAULT_SUBSCRIBE_PLACEHOLDER,
@@ -112,6 +115,15 @@ export function SubscriptionEdit( props ) {
112115
};
113116
} );
114117

118+
const { availableNewsletterCategories, areNewsletterCategoriesEnabled } = useSelect( select => {
119+
const store = select( membershipProductsStore );
120+
121+
return {
122+
availableNewsletterCategories: store.getNewsletterCategories(),
123+
areNewsletterCategoriesEnabled: store.getNewsletterCategoriesEnabled(),
124+
};
125+
} );
126+
115127
const emailFieldGradient = useGradientIfAvailable( {
116128
gradientAttribute: 'emailFieldGradient',
117129
customGradientAttribute: 'customEmailFieldGradient',
@@ -225,6 +237,8 @@ export function SubscriptionEdit( props ) {
225237
>
226238
<InspectorControls>
227239
<SubscriptionControls
240+
areNewsletterCategoriesEnabled={ areNewsletterCategoriesEnabled }
241+
availableNewsletterCategories={ availableNewsletterCategories }
228242
buttonBackgroundColor={ buttonBackgroundColor }
229243
borderColor={ borderColor }
230244
buttonGradient={ buttonGradient }
@@ -238,6 +252,7 @@ export function SubscriptionEdit( props ) {
238252
includeSocialFollowers={ includeSocialFollowers }
239253
isGradientAvailable={ isGradientAvailable }
240254
padding={ padding }
255+
preselectNewsletterCategories={ preselectNewsletterCategories }
241256
setAttributes={ setAttributes }
242257
setBorderColor={ setBorderColor }
243258
setButtonBackgroundColor={ setButtonBackgroundColor }
@@ -247,6 +262,7 @@ export function SubscriptionEdit( props ) {
247262
subscriberCount={ subscriberCount }
248263
textColor={ textColor }
249264
buttonWidth={ buttonWidth }
265+
selectedNewsletterCategoryIds={ selectedNewsletterCategoryIds }
250266
subscribePlaceholder={ subscribePlaceholder }
251267
submitButtonText={ submitButtonText }
252268
successMessage={ successMessage }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.wp-block-jetpack-subscriptions__legend { // Meant to mimic .components-base-control__label
2+
font-size: 11px;
3+
font-weight: 500;
4+
line-height: 1.4;
5+
text-transform: uppercase;
6+
display: block;
7+
margin-bottom: 8px;
8+
padding: 0px;
9+
}

projects/plugins/jetpack/extensions/blocks/subscriptions/subscriptions.php

+21-15
Original file line numberDiff line numberDiff line change
@@ -665,32 +665,34 @@ function render_block( $attributes ) {
665665
$include_social_followers = isset( $attributes['includeSocialFollowers'] ) ? (bool) get_attribute( $attributes, 'includeSocialFollowers' ) : true;
666666

667667
$data = array(
668-
'widget_id' => Jetpack_Subscriptions_Widget::$instance_count,
669-
'subscribe_email' => $subscribe_email,
670-
'is_paid_subscriber' => get_attribute( $attributes, 'isPaidSubscriber', false ),
671-
'wrapper_attributes' => get_block_wrapper_attributes(
668+
'widget_id' => Jetpack_Subscriptions_Widget::$instance_count,
669+
'subscribe_email' => $subscribe_email,
670+
'is_paid_subscriber' => get_attribute( $attributes, 'isPaidSubscriber', false ),
671+
'wrapper_attributes' => get_block_wrapper_attributes(
672672
array(
673673
'class' => $classes['block_wrapper'],
674674
)
675675
),
676-
'subscribe_placeholder' => get_attribute( $attributes, 'subscribePlaceholder', __( 'Type your email…', 'jetpack' ) ),
677-
'submit_button_text' => get_attribute( $attributes, 'submitButtonText', __( 'Subscribe', 'jetpack' ) ),
678-
'submit_button_text_subscribed' => get_attribute( $attributes, 'submitButtonTextSubscribed', __( 'Subscribed', 'jetpack' ) ),
679-
'submit_button_text_upgrade' => get_attribute( $attributes, 'submitButtonTextUpgrade', __( 'Upgrade subscription', 'jetpack' ) ),
680-
'success_message' => get_attribute(
676+
'subscribe_placeholder' => get_attribute( $attributes, 'subscribePlaceholder', __( 'Type your email…', 'jetpack' ) ),
677+
'submit_button_text' => get_attribute( $attributes, 'submitButtonText', __( 'Subscribe', 'jetpack' ) ),
678+
'submit_button_text_subscribed' => get_attribute( $attributes, 'submitButtonTextSubscribed', __( 'Subscribed', 'jetpack' ) ),
679+
'submit_button_text_upgrade' => get_attribute( $attributes, 'submitButtonTextUpgrade', __( 'Upgrade subscription', 'jetpack' ) ),
680+
'success_message' => get_attribute(
681681
$attributes,
682682
'successMessage',
683683
esc_html__( "Success! An email was just sent to confirm your subscription. Please find the email now and click 'Confirm' to start subscribing.", 'jetpack' )
684684
),
685-
'show_subscribers_total' => (bool) get_attribute( $attributes, 'showSubscribersTotal' ),
686-
'subscribers_total' => get_attribute( $attributes, 'showSubscribersTotal' ) ? get_subscriber_count( $include_social_followers ) : 0,
687-
'referer' => esc_url_raw(
685+
'show_subscribers_total' => (bool) get_attribute( $attributes, 'showSubscribersTotal' ),
686+
'subscribers_total' => get_attribute( $attributes, 'showSubscribersTotal' ) ? get_subscriber_count( $include_social_followers ) : 0,
687+
'referer' => esc_url_raw(
688688
( is_ssl() ? 'https' : 'http' ) . '://' . ( isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : '' ) .
689689
( isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '' )
690690
),
691-
'source' => 'subscribe-block',
692-
'app_source' => get_attribute( $attributes, 'appSource', null ),
693-
'class_name' => get_attribute( $attributes, 'className' ),
691+
'source' => 'subscribe-block',
692+
'app_source' => get_attribute( $attributes, 'appSource', null ),
693+
'class_name' => get_attribute( $attributes, 'className' ),
694+
'selected_newsletter_categories' => get_attribute( $attributes, 'selectedNewsletterCategoryIds', array() ),
695+
'preselected_newsletter_categories' => get_attribute( $attributes, 'preselectNewsletterCategories', false ),
694696
);
695697

696698
if ( ! jetpack_is_frontend() ) {
@@ -850,6 +852,10 @@ class="screen-reader-text"
850852
if ( ! empty( $tier_id ) ) {
851853
echo '<input type="hidden" name="tier_id" value="' . esc_attr( $tier_id ) . '"/>';
852854
}
855+
856+
if ( $data['preselected_newsletter_categories'] && ! empty( $data['selected_newsletter_categories'] ) ) {
857+
echo '<input type="hidden" name="selected_newsletter_categories" value="' . esc_attr( implode( ',', $data['selected_newsletter_categories'] ) ) . '"/>';
858+
}
853859
?>
854860
<button type="submit"
855861
<?php if ( ! empty( $classes['submit_button'] ) ) : ?>

projects/plugins/jetpack/extensions/blocks/subscriptions/test/controls.js

+102
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ const defaultProps = {
7575
spacing: 0,
7676
subscriberCount: 100,
7777
textColor: '#000000',
78+
areNewsletterCategoriesEnabled: true,
79+
availableNewsletterCategories: [
80+
{ id: 1, name: 'Category 1' },
81+
{ id: 2, name: 'Category 2' },
82+
],
83+
preselectNewsletterCategories: false,
84+
selectedNewsletterCategoryIds: [],
7885
};
7986

8087
beforeEach( () => {
@@ -257,5 +264,100 @@ describe( 'Inspector controls', () => {
257264
buttonOnNewLine: true,
258265
} );
259266
} );
267+
268+
describe( 'Newsletter categories', () => {
269+
test( 'displays newsletter category controls when enabled', async () => {
270+
const user = userEvent.setup();
271+
render( <SubscriptionsInspectorControls { ...defaultProps } /> );
272+
273+
await user.click( screen.getByText( 'Settings' ), { selector: 'button' } );
274+
275+
expect( screen.getByText( 'Pre-select categories' ) ).toBeInTheDocument();
276+
} );
277+
278+
test( 'does not render controls when newsletter categories are disabled', async () => {
279+
const user = userEvent.setup();
280+
render(
281+
<SubscriptionsInspectorControls
282+
{ ...defaultProps }
283+
areNewsletterCategoriesEnabled={ false }
284+
/>
285+
);
286+
287+
await user.click( screen.getByText( 'Settings' ), { selector: 'button' } );
288+
289+
expect( screen.queryByText( 'Pre-select categories' ) ).not.toBeInTheDocument();
290+
expect( screen.queryByText( 'Categories' ) ).not.toBeInTheDocument();
291+
} );
292+
293+
test( 'does not render controls when there are no categories', async () => {
294+
const user = userEvent.setup();
295+
render(
296+
<SubscriptionsInspectorControls
297+
{ ...defaultProps }
298+
availableNewsletterCategories={ [] }
299+
/>
300+
);
301+
302+
await user.click( screen.getByText( 'Settings' ), { selector: 'button' } );
303+
304+
expect( screen.queryByText( 'Pre-select categories' ) ).not.toBeInTheDocument();
305+
expect( screen.queryByText( 'Categories' ) ).not.toBeInTheDocument();
306+
} );
307+
308+
test( 'selects categories', async () => {
309+
const user = userEvent.setup();
310+
render(
311+
<SubscriptionsInspectorControls { ...defaultProps } preselectNewsletterCategories />
312+
);
313+
314+
await user.click( screen.getByText( 'Settings' ), { selector: 'button' } );
315+
await user.click( screen.getByLabelText( 'Category 1' ) );
316+
317+
expect( setAttributes ).toHaveBeenCalledWith( {
318+
selectedNewsletterCategoryIds: [ defaultProps.availableNewsletterCategories[ 0 ].id ],
319+
} );
320+
} );
321+
322+
test( 'toggles category selection', async () => {
323+
const user = userEvent.setup();
324+
render(
325+
<SubscriptionsInspectorControls
326+
{ ...defaultProps }
327+
preselectNewsletterCategories
328+
selectedNewsletterCategoryIds={ [
329+
defaultProps.availableNewsletterCategories[ 0 ].id,
330+
defaultProps.availableNewsletterCategories[ 1 ].id,
331+
] }
332+
/>
333+
);
334+
335+
await user.click( screen.getByText( 'Settings' ), { selector: 'button' } );
336+
await user.click( screen.getByLabelText( 'Category 1' ) );
337+
338+
expect( setAttributes ).toHaveBeenCalledWith( {
339+
selectedNewsletterCategoryIds: [ defaultProps.availableNewsletterCategories[ 1 ].id ],
340+
} );
341+
} );
342+
343+
test( 'toggles pre-select control when all categories are unchecked', async () => {
344+
const user = userEvent.setup();
345+
render(
346+
<SubscriptionsInspectorControls
347+
{ ...defaultProps }
348+
preselectNewsletterCategories
349+
selectedNewsletterCategoryIds={ [ defaultProps.availableNewsletterCategories[ 0 ].id ] }
350+
/>
351+
);
352+
353+
await user.click( screen.getByText( 'Settings' ), { selector: 'button' } );
354+
await user.click( screen.getByLabelText( 'Category 1' ) );
355+
356+
expect( setAttributes ).toHaveBeenCalledWith( {
357+
selectedNewsletterCategoryIds: [],
358+
preselectNewsletterCategories: false,
359+
} );
360+
} );
361+
} );
260362
} );
261363
} );

projects/plugins/jetpack/extensions/blocks/subscriptions/test/fixtures/jetpack__subscriptions.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
"borderRadius": 8,
1515
"borderWeight": 3,
1616
"padding": 18,
17-
"successMessage": "Volla, you subscribed to our blog!"
17+
"successMessage": "Volla, you subscribed to our blog!",
18+
"preselectNewsletterCategories": false,
19+
"selectedNewsletterCategoryIds": []
1820
},
1921
"innerBlocks": [],
2022
"originalContent": ""

projects/plugins/jetpack/extensions/blocks/subscriptions/test/fixtures/jetpack__subscriptions__deprecated-8.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"borderRadius": 8,
1414
"borderWeight": 3,
1515
"padding": 18,
16-
"successMessage": "Volla, you subscribed to our blog!"
16+
"successMessage": "Volla, you subscribed to our blog!",
17+
"preselectNewsletterCategories": false,
18+
"selectedNewsletterCategoryIds": []
1719
},
1820
"innerBlocks": [],
1921
"originalContent": ""

projects/plugins/jetpack/extensions/blocks/subscriptions/view.js

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ domReady( function () {
8181
const post_id = form.querySelector( 'input[name=post_id]' )?.value ?? '';
8282
const tier_id = form.querySelector( 'input[name=tier_id]' )?.value ?? '';
8383
const app_source = form.querySelector( 'input[name=app_source]' )?.value ?? '';
84+
const selected_newsletter_categories =
85+
form.querySelector( 'input[name=selected_newsletter_categories]' )?.value ?? '';
8486

8587
show_iframe( {
8688
email,
@@ -92,6 +94,7 @@ domReady( function () {
9294
app_source,
9395
post_access_level: form.dataset.post_access_level,
9496
display: 'alternate',
97+
selected_newsletter_categories,
9598
} ).then( () => {
9699
// Allows hiding other modals when the subscription modal/iframe shows up, e.g. hiding the subscription overlay modal
97100
form.dispatchEvent( new Event( 'subscription-modal-loaded' ) );

0 commit comments

Comments
 (0)