Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit 1cbc69f

Browse files
authored
Update the sidebar notice we show for incompatible extensions (#10877)
* Adkust text of sidebar notice * Adjust text of sidebar notice * Rename folder to “incompatible-extension-notice” * Rename main component and interface * Rename constants * Add new files for splitting logic * WIP: Semi-hardcoded solution * WIP: Add new data store * Fetch incompatible extensions dynamically * Fix broken dismiss notice functionality * Minor refactor * Remove data store * Remove console.log * Remove obsolete data store fragment * Update package-lock.json and composer.lock * Change wording from “might be” to “may be” * Show single incompatible extension within notice instead of as list * Fix *.md linting error
1 parent 0e57f14 commit 1cbc69f

File tree

11 files changed

+318
-187
lines changed

11 files changed

+318
-187
lines changed

assets/js/blocks/cart-checkout-shared/sidebar-notices/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { CartCheckoutSidebarCompatibilityNotice } from '@woocommerce/editor-comp
1212
import { NoPaymentMethodsNotice } from '@woocommerce/editor-components/no-payment-methods-notice';
1313
import { PAYMENT_STORE_KEY } from '@woocommerce/block-data';
1414
import { DefaultNotice } from '@woocommerce/editor-components/default-notice';
15-
import { IncompatiblePaymentGatewaysNotice } from '@woocommerce/editor-components/incompatible-payment-gateways-notice';
15+
import { IncompatibleExtensionsNotice } from '@woocommerce/editor-components/incompatible-extension-notice';
1616
import { useSelect } from '@wordpress/data';
1717
import { CartCheckoutFeedbackPrompt } from '@woocommerce/editor-components/feedback-prompt';
1818
import { useState } from '@wordpress/element';
@@ -38,14 +38,14 @@ const withSidebarNotices = createHigherOrderComponent(
3838
} = props;
3939

4040
const [
41-
isIncompatiblePaymentGatewaysNoticeDismissed,
42-
setIsIncompatiblePaymentGatewaysNoticeDismissed,
41+
isIncompatibleExtensionsNoticeDismissed,
42+
setIsIncompatibleExtensionsNoticeDismissed,
4343
] = useState( true );
4444

45-
const toggleIncompatiblePaymentGatewaysNoticeDismissedStatus = (
45+
const toggleIncompatibleExtensionsNoticeDismissedStatus = (
4646
isDismissed: boolean
4747
) => {
48-
setIsIncompatiblePaymentGatewaysNoticeDismissed( isDismissed );
48+
setIsIncompatibleExtensionsNoticeDismissed( isDismissed );
4949
};
5050

5151
const { isCart, isCheckout, isPaymentMethodsBlock, hasPaymentMethods } =
@@ -91,9 +91,9 @@ const withSidebarNotices = createHigherOrderComponent(
9191
return (
9292
<>
9393
<InspectorControls>
94-
<IncompatiblePaymentGatewaysNotice
94+
<IncompatibleExtensionsNotice
9595
toggleDismissedStatus={
96-
toggleIncompatiblePaymentGatewaysNoticeDismissedStatus
96+
toggleIncompatibleExtensionsNoticeDismissedStatus
9797
}
9898
block={
9999
isCheckout
@@ -104,7 +104,7 @@ const withSidebarNotices = createHigherOrderComponent(
104104

105105
<DefaultNotice block={ isCheckout ? 'checkout' : 'cart' } />
106106

107-
{ isIncompatiblePaymentGatewaysNoticeDismissed ? (
107+
{ isIncompatibleExtensionsNoticeDismissed ? (
108108
<CartCheckoutSidebarCompatibilityNotice
109109
block={ isCheckout ? 'checkout' : 'cart' }
110110
/>

assets/js/data/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import '@wordpress/notices';
66
/**
77
* Internal dependencies
88
*/
9-
export { SCHEMA_STORE_KEY } from './schema';
10-
export { COLLECTIONS_STORE_KEY } from './collections';
119
export { CART_STORE_KEY } from './cart';
1210
export { CHECKOUT_STORE_KEY } from './checkout';
11+
export { COLLECTIONS_STORE_KEY } from './collections';
1312
export { PAYMENT_STORE_KEY } from './payment';
14-
export { VALIDATION_STORE_KEY } from './validation';
1513
export { QUERY_STATE_STORE_KEY } from './query-state';
14+
export { SCHEMA_STORE_KEY } from './schema';
1615
export { STORE_NOTICES_STORE_KEY } from './store-notices';
16+
export { VALIDATION_STORE_KEY } from './validation';
1717
export * from './constants';
1818
export * from './utils';
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { __, sprintf } from '@wordpress/i18n';
5+
import { Notice, ExternalLink } from '@wordpress/components';
6+
import { createInterpolateElement, useEffect } from '@wordpress/element';
7+
import { Alert } from '@woocommerce/icons';
8+
import { Icon } from '@wordpress/icons';
9+
/**
10+
* Internal dependencies
11+
*/
12+
import { useCombinedIncompatibilityNotice } from './use-combined-incompatibility-notice';
13+
import './editor.scss';
14+
15+
interface ExtensionNoticeProps {
16+
toggleDismissedStatus: ( status: boolean ) => void;
17+
block: 'woocommerce/cart' | 'woocommerce/checkout';
18+
}
19+
20+
export function IncompatibleExtensionsNotice( {
21+
toggleDismissedStatus,
22+
block,
23+
}: ExtensionNoticeProps ) {
24+
const [
25+
isVisible,
26+
dismissNotice,
27+
incompatiblePaymentMethods,
28+
numberOfIncompatiblePaymentMethods,
29+
] = useCombinedIncompatibilityNotice( block );
30+
31+
useEffect( () => {
32+
toggleDismissedStatus( ! isVisible );
33+
}, [ isVisible, toggleDismissedStatus ] );
34+
35+
if ( ! isVisible ) {
36+
return null;
37+
}
38+
39+
// console.log( incompatiblePaymentMethods );
40+
41+
const noticeContent = (
42+
<>
43+
{ numberOfIncompatiblePaymentMethods > 1
44+
? createInterpolateElement(
45+
__(
46+
'The following extensions may be incompatible with the block-based checkout. <a>Learn more</a>',
47+
'woo-gutenberg-products-block'
48+
),
49+
{
50+
a: (
51+
<ExternalLink href="https://woocommerce.com/document/cart-checkout-blocks-support-status/" />
52+
),
53+
}
54+
)
55+
: createInterpolateElement(
56+
sprintf(
57+
// translators: %s is the name of the extension that is incompatible with the block-based checkout.
58+
__(
59+
'<strong>%s</strong> may be incompatible with the block-based checkout. <a>Learn more</a>',
60+
'woo-gutenberg-products-block'
61+
),
62+
Object.values( incompatiblePaymentMethods )[ 0 ]
63+
),
64+
{
65+
strong: <strong />,
66+
a: (
67+
<ExternalLink href="https://woocommerce.com/document/cart-checkout-blocks-support-status/" />
68+
),
69+
}
70+
) }
71+
</>
72+
);
73+
74+
return (
75+
<Notice
76+
className="wc-blocks-incompatible-extensions-notice"
77+
status={ 'warning' }
78+
onRemove={ dismissNotice }
79+
spokenMessage={ noticeContent }
80+
>
81+
<div className="wc-blocks-incompatible-extensions-notice__content">
82+
<Icon
83+
className="wc-blocks-incompatible-extensions-notice__warning-icon"
84+
icon={ <Alert /> }
85+
/>
86+
<div>
87+
<p>{ noticeContent }</p>
88+
{ numberOfIncompatiblePaymentMethods > 1 && (
89+
<ul>
90+
{ Object.entries( incompatiblePaymentMethods ).map(
91+
( [ id, title ] ) => (
92+
<li
93+
key={ id }
94+
className="wc-blocks-incompatible-extensions-notice__element"
95+
>
96+
{ title }
97+
</li>
98+
)
99+
) }
100+
</ul>
101+
) }
102+
</div>
103+
</div>
104+
</Notice>
105+
);
106+
}
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
/**
22
* External dependencies
33
*/
4-
import { useSelect } from '@wordpress/data';
5-
import { useEffect, useState } from '@wordpress/element';
4+
import { useState, useEffect } from '@wordpress/element';
65
import { useLocalStorageState } from '@woocommerce/base-hooks';
76

87
/**
98
* Internal dependencies
109
*/
11-
import { STORE_KEY as PAYMENT_STORE_KEY } from '../../data/payment/constants';
10+
import { useIncompatiblePaymentGatewaysNotice } from './use-incompatible-payment-gateways-notice';
11+
import { useIncompatibleExtensionNotice } from './use-incompatible-extensions-notice';
1212

13-
type StoredIncompatibleGateway = { [ k: string ]: string[] };
13+
type StoredIncompatibleExtension = { [ k: string ]: string[] };
1414
const initialDismissedNotices: React.SetStateAction<
15-
StoredIncompatibleGateway[]
15+
StoredIncompatibleExtension[]
1616
> = [];
1717

1818
const areEqual = ( array1: string[], array2: string[] ) => {
@@ -25,44 +25,68 @@ const areEqual = ( array1: string[], array2: string[] ) => {
2525
return uniqueCollectionValues.size === array1.length;
2626
};
2727

28-
export const useIncompatiblePaymentGatewaysNotice = (
28+
const sortAlphabetically = ( obj: {
29+
[ key: string ]: string;
30+
} ): { [ key: string ]: string } =>
31+
Object.fromEntries(
32+
Object.entries( obj ).sort( ( [ , a ], [ , b ] ) =>
33+
a.localeCompare( b )
34+
)
35+
);
36+
37+
export const useCombinedIncompatibilityNotice = (
2938
blockName: string
3039
): [ boolean, () => void, { [ k: string ]: string }, number ] => {
40+
const [
41+
incompatibleExtensions,
42+
incompatibleExtensionSlugs,
43+
incompatibleExtensionCount,
44+
] = useIncompatibleExtensionNotice();
45+
46+
const [
47+
incompatiblePaymentMethods,
48+
incompatiblePaymentMethodSlugs,
49+
incompatiblePaymentMethodCount,
50+
] = useIncompatiblePaymentGatewaysNotice();
51+
52+
const allIncompatibleItems = {
53+
...incompatibleExtensions,
54+
...incompatiblePaymentMethods,
55+
};
56+
57+
const allIncompatibleItemSlugs = [
58+
...incompatibleExtensionSlugs,
59+
...incompatiblePaymentMethodSlugs,
60+
];
61+
62+
const allIncompatibleItemCount =
63+
incompatibleExtensionCount + incompatiblePaymentMethodCount;
64+
3165
const [ dismissedNotices, setDismissedNotices ] = useLocalStorageState<
32-
StoredIncompatibleGateway[]
66+
StoredIncompatibleExtension[]
3367
>(
34-
`wc-blocks_dismissed_incompatible_payment_gateways_notices`,
68+
`wc-blocks_dismissed_incompatible_extensions_notices`,
3569
initialDismissedNotices
3670
);
37-
const [ isVisible, setIsVisible ] = useState( false );
3871

39-
const { incompatiblePaymentMethods } = useSelect( ( select ) => {
40-
const { getIncompatiblePaymentMethods } = select( PAYMENT_STORE_KEY );
41-
return {
42-
incompatiblePaymentMethods: getIncompatiblePaymentMethods(),
43-
};
44-
}, [] );
45-
const incompatiblePaymentMethodsIDs = Object.keys(
46-
incompatiblePaymentMethods
47-
);
48-
const numberOfIncompatiblePaymentMethods =
49-
incompatiblePaymentMethodsIDs.length;
72+
const [ isVisible, setIsVisible ] = useState( false );
5073

5174
const isDismissedNoticeUpToDate = dismissedNotices.some(
5275
( notice ) =>
5376
Object.keys( notice ).includes( blockName ) &&
5477
areEqual(
5578
notice[ blockName as keyof object ],
56-
incompatiblePaymentMethodsIDs
79+
allIncompatibleItemSlugs
5780
)
5881
);
5982

6083
const shouldBeDismissed =
61-
numberOfIncompatiblePaymentMethods === 0 || isDismissedNoticeUpToDate;
84+
allIncompatibleItemCount === 0 || isDismissedNoticeUpToDate;
85+
6286
const dismissNotice = () => {
6387
const dismissedNoticesSet = new Set( dismissedNotices );
6488
dismissedNoticesSet.add( {
65-
[ blockName ]: incompatiblePaymentMethodsIDs,
89+
[ blockName ]: allIncompatibleItemSlugs,
6690
} );
6791
setDismissedNotices( [ ...dismissedNoticesSet ] );
6892
};
@@ -75,7 +99,7 @@ export const useIncompatiblePaymentGatewaysNotice = (
7599
if ( ! shouldBeDismissed && ! isDismissedNoticeUpToDate ) {
76100
setDismissedNotices( ( previousDismissedNotices ) =>
77101
previousDismissedNotices.reduce(
78-
( acc: StoredIncompatibleGateway[], curr ) => {
102+
( acc: StoredIncompatibleExtension[], curr ) => {
79103
if ( Object.keys( curr ).includes( blockName ) ) {
80104
return acc;
81105
}
@@ -97,7 +121,7 @@ export const useIncompatiblePaymentGatewaysNotice = (
97121
return [
98122
isVisible,
99123
dismissNotice,
100-
incompatiblePaymentMethods,
101-
numberOfIncompatiblePaymentMethods,
124+
sortAlphabetically( allIncompatibleItems ),
125+
allIncompatibleItemCount,
102126
];
103127
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { getSetting } from '@woocommerce/settings';
5+
6+
export const useIncompatibleExtensionNotice = (): [
7+
{ [ k: string ]: string } | null,
8+
string[],
9+
number
10+
] => {
11+
interface GlobalIncompatibleExtensions {
12+
id: string;
13+
title: string;
14+
}
15+
16+
const incompatibleExtensions: Record< string, string > = {};
17+
18+
if ( getSetting( 'incompatibleExtensions' ) ) {
19+
getSetting< GlobalIncompatibleExtensions[] >(
20+
'incompatibleExtensions'
21+
).forEach( ( extension ) => {
22+
incompatibleExtensions[ extension.id ] = extension.title;
23+
} );
24+
}
25+
26+
const incompatibleExtensionSlugs = Object.keys( incompatibleExtensions );
27+
const incompatibleExtensionCount = incompatibleExtensionSlugs.length;
28+
29+
return [
30+
incompatibleExtensions,
31+
incompatibleExtensionSlugs,
32+
incompatibleExtensionCount,
33+
];
34+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { useSelect } from '@wordpress/data';
5+
6+
/**
7+
* Internal dependencies
8+
*/
9+
import { STORE_KEY as PAYMENT_STORE_KEY } from '../../data/payment/constants';
10+
11+
export const useIncompatiblePaymentGatewaysNotice = (): [
12+
{ [ k: string ]: string },
13+
string[],
14+
number
15+
] => {
16+
const { incompatiblePaymentMethods } = useSelect( ( select ) => {
17+
const { getIncompatiblePaymentMethods } = select( PAYMENT_STORE_KEY );
18+
return {
19+
incompatiblePaymentMethods: getIncompatiblePaymentMethods(),
20+
};
21+
}, [] );
22+
23+
const incompatiblePaymentMethodSlugs = Object.keys(
24+
incompatiblePaymentMethods
25+
);
26+
27+
const incompatiblePaymentMethodCount =
28+
incompatiblePaymentMethodSlugs.length;
29+
30+
return [
31+
incompatiblePaymentMethods,
32+
incompatiblePaymentMethodSlugs,
33+
incompatiblePaymentMethodCount,
34+
];
35+
};

0 commit comments

Comments
 (0)