From 4ca5fab505400412d59947971bf1fa0c8bf3c56a Mon Sep 17 00:00:00 2001 From: Tom Cafferkey Date: Wed, 28 Oct 2020 13:52:32 +0000 Subject: [PATCH 1/4] Update EditorCheckoutModal to use ShoppingCartProvider --- client/blocks/editor-checkout-modal/index.tsx | 111 +++++++++--------- client/blocks/editor-checkout-modal/types.ts | 18 +++ client/gutenberg/editor/calypsoify-iframe.tsx | 2 +- 3 files changed, 76 insertions(+), 55 deletions(-) create mode 100644 client/blocks/editor-checkout-modal/types.ts diff --git a/client/blocks/editor-checkout-modal/index.tsx b/client/blocks/editor-checkout-modal/index.tsx index 7878b764b751d..6581e4394f54e 100644 --- a/client/blocks/editor-checkout-modal/index.tsx +++ b/client/blocks/editor-checkout-modal/index.tsx @@ -1,12 +1,13 @@ /** * External dependencies */ -import React, { Component } from 'react'; +import React, { useMemo } from 'react'; import { connect } from 'react-redux'; import wp from 'calypso/lib/wp'; import classnames from 'classnames'; import { Button } from '@wordpress/components'; import { Icon, close, wordpress } from '@wordpress/icons'; +import { ShoppingCartProvider } from '@automattic/shopping-cart'; /** * Internal dependencies @@ -15,6 +16,10 @@ import { StripeHookProvider } from 'calypso/lib/stripe'; import { fetchStripeConfiguration } from 'calypso/my-sites/checkout/composite-checkout/payment-method-helpers'; import CompositeCheckout from 'calypso/my-sites/checkout/composite-checkout/composite-checkout'; import { getSelectedSite } from 'calypso/state/ui/selectors'; +import getCartKey from 'calypso/my-sites/checkout/get-cart-key'; +import type { SiteData } from 'calypso/state/ui/selectors/site-data'; +import userFactory from 'calypso/lib/user'; +import type { CartData, Props } from './types'; /** * Style dependencies @@ -23,74 +28,72 @@ import './style.scss'; const wpcom = wp.undocumented(); -type Site = { - ID: number; - slug: string; -}; - -export interface CartData { - products: Array< { - product_id: number; - product_slug: string; - } >; +async function getCart( site: SiteData, cartData: CartData ) { + try { + return await wpcom.setCart( site.ID, cartData ); + } catch { + return; + } } -type Props = { - site: Site; - cartData: CartData; - onClose: () => void; - isOpen: boolean; -}; - -class EditorCheckoutModal extends Component< Props > { - static defaultProps = { - isOpen: false, - onClose: () => null, - cartData: {}, - }; - - async getCart() { - // Important: If getCart or cartData is empty, it will redirect to the plans page in customer home. - const { site, cartData } = this.props; +function fetchStripeConfigurationWpcom( args: Record< string, unknown > ) { + return fetchStripeConfiguration( args, wpcom ); +} - try { - return await wpcom.setCart( site.ID, cartData ); - } catch { - return; - } - } +const EditorCheckoutModal = ( props: Props ) => { + const { site, isOpen, onClose, cartData } = props; + const hasEmptyCart = ! cartData.products || cartData.products.length < 1; - render() { - const { site, isOpen, onClose, cartData } = this.props; + const user = userFactory(); + const isLoggedOutCart = ! user?.get(); + const waitForOtherCartUpdates = false; + // We can assume if they're accessing the checkout in an editor that they have a site. + const isNoSiteCart = false; - const hasEmptyCart = ! cartData.products || cartData.products.length < 1; + const cartKey = useMemo( + () => + getCartKey( { + selectedSite: site, + isLoggedOutCart, + isNoSiteCart, + waitForOtherCartUpdates, + } ), + [ waitForOtherCartUpdates, site, isLoggedOutCart, isNoSiteCart ] + ); - return hasEmptyCart ? null : ( -
-
-
- -
- + return hasEmptyCart ? null : ( +
+
+
+
+ +
+ getCart( site, cartData ) } + setCart={ () => getCart( site, cartData ) } + > getCart( site, cartData ) } /> -
- ); - } -} + +
+ ); +}; -function fetchStripeConfigurationWpcom( args: Record< string, unknown > ) { - return fetchStripeConfiguration( args, wpcom ); -} +EditorCheckoutModal.defaultProps = { + isOpen: false, + onClose: () => null, + cartData: {}, +}; export default connect( ( state ) => ( { site: getSelectedSite( state ), diff --git a/client/blocks/editor-checkout-modal/types.ts b/client/blocks/editor-checkout-modal/types.ts new file mode 100644 index 0000000000000..fd5b3cc31fa29 --- /dev/null +++ b/client/blocks/editor-checkout-modal/types.ts @@ -0,0 +1,18 @@ +/** + * Internal dependencies + */ +import type { SiteData } from 'calypso/state/ui/selectors/site-data'; + +export interface CartData { + products: Array< { + product_id: number; + product_slug: string; + } >; +} + +export type Props = { + site: SiteData; + cartData: CartData; + onClose: () => void; + isOpen: boolean; +}; diff --git a/client/gutenberg/editor/calypsoify-iframe.tsx b/client/gutenberg/editor/calypsoify-iframe.tsx index 55e3198dd2c62..edd5794ebb0fd 100644 --- a/client/gutenberg/editor/calypsoify-iframe.tsx +++ b/client/gutenberg/editor/calypsoify-iframe.tsx @@ -56,7 +56,7 @@ import { REASON_BLOCK_EDITOR_UNKOWN_IFRAME_LOAD_FAILURE } from 'calypso/state/de import { setMediaLibrarySelectedItems } from 'calypso/state/media/actions'; import { fetchMediaItem, getMediaItem } from 'calypso/state/media/thunks'; import Iframe from './iframe'; -import type { CartData } from 'calypso/client/blocks/editor-checkout-modal'; +import type { CartData } from 'calypso/client/blocks/editor-checkout-modal/types'; /** * Types From fcafcf0f85278a40fbf18cf3b00a967ef41cdd34 Mon Sep 17 00:00:00 2001 From: Tom Cafferkey Date: Thu, 29 Oct 2020 09:42:20 +0000 Subject: [PATCH 2/4] Pass in productSlugs to CompositeCheckout to load products into users cart prior to opening modal. --- client/blocks/editor-checkout-modal/index.tsx | 36 +++++++++++-------- client/blocks/editor-checkout-modal/types.ts | 18 ---------- 2 files changed, 21 insertions(+), 33 deletions(-) delete mode 100644 client/blocks/editor-checkout-modal/types.ts diff --git a/client/blocks/editor-checkout-modal/index.tsx b/client/blocks/editor-checkout-modal/index.tsx index 6581e4394f54e..41f3bb9a16012 100644 --- a/client/blocks/editor-checkout-modal/index.tsx +++ b/client/blocks/editor-checkout-modal/index.tsx @@ -7,7 +7,7 @@ import wp from 'calypso/lib/wp'; import classnames from 'classnames'; import { Button } from '@wordpress/components'; import { Icon, close, wordpress } from '@wordpress/icons'; -import { ShoppingCartProvider } from '@automattic/shopping-cart'; +import { ShoppingCartProvider, RequestCart } from '@automattic/shopping-cart'; /** * Internal dependencies @@ -19,7 +19,6 @@ import { getSelectedSite } from 'calypso/state/ui/selectors'; import getCartKey from 'calypso/my-sites/checkout/get-cart-key'; import type { SiteData } from 'calypso/state/ui/selectors/site-data'; import userFactory from 'calypso/lib/user'; -import type { CartData, Props } from './types'; /** * Style dependencies @@ -28,13 +27,9 @@ import './style.scss'; const wpcom = wp.undocumented(); -async function getCart( site: SiteData, cartData: CartData ) { - try { - return await wpcom.setCart( site.ID, cartData ); - } catch { - return; - } -} +const wpcomGetCart = ( cartKey: string ) => wpcom.getCart( cartKey ); +const wpcomSetCart = ( cartKey: string, requestCart: RequestCart ) => + wpcom.setCart( cartKey, requestCart ); function fetchStripeConfigurationWpcom( args: Record< string, unknown > ) { return fetchStripeConfiguration( args, wpcom ); @@ -61,6 +56,14 @@ const EditorCheckoutModal = ( props: Props ) => { [ waitForOtherCartUpdates, site, isLoggedOutCart, isNoSiteCart ] ); + // We need to pass in a comma separated list of product + // slugs to be set in the cart otherwise we will be + // redirected to the plans page due to an empty cart + const productSlugs = hasEmptyCart + ? null + : cartData.products.map( ( product ) => product.product_slug ); + const commaSeparatedProductSlugs = productSlugs?.join( ',' ) || null; + return hasEmptyCart ? null : (
@@ -71,17 +74,13 @@ const EditorCheckoutModal = ( props: Props ) => {
- getCart( site, cartData ) } - setCart={ () => getCart( site, cartData ) } - > + getCart( site, cartData ) } + productAliasFromUrl={ commaSeparatedProductSlugs } /> @@ -89,6 +88,13 @@ const EditorCheckoutModal = ( props: Props ) => { ); }; +type Props = { + site: SiteData; + cartData: RequestCart; + onClose: () => void; + isOpen: boolean; +}; + EditorCheckoutModal.defaultProps = { isOpen: false, onClose: () => null, diff --git a/client/blocks/editor-checkout-modal/types.ts b/client/blocks/editor-checkout-modal/types.ts deleted file mode 100644 index fd5b3cc31fa29..0000000000000 --- a/client/blocks/editor-checkout-modal/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Internal dependencies - */ -import type { SiteData } from 'calypso/state/ui/selectors/site-data'; - -export interface CartData { - products: Array< { - product_id: number; - product_slug: string; - } >; -} - -export type Props = { - site: SiteData; - cartData: CartData; - onClose: () => void; - isOpen: boolean; -}; From 2c146d8ac5141442501f9b93393992f60d30af80 Mon Sep 17 00:00:00 2001 From: Tom Cafferkey Date: Thu, 29 Oct 2020 10:20:07 +0000 Subject: [PATCH 3/4] Replace CartData type with RequestCart type from @automattic/shopping-cart --- client/gutenberg/editor/calypsoify-iframe.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/gutenberg/editor/calypsoify-iframe.tsx b/client/gutenberg/editor/calypsoify-iframe.tsx index edd5794ebb0fd..4b148fd9283f8 100644 --- a/client/gutenberg/editor/calypsoify-iframe.tsx +++ b/client/gutenberg/editor/calypsoify-iframe.tsx @@ -56,7 +56,7 @@ import { REASON_BLOCK_EDITOR_UNKOWN_IFRAME_LOAD_FAILURE } from 'calypso/state/de import { setMediaLibrarySelectedItems } from 'calypso/state/media/actions'; import { fetchMediaItem, getMediaItem } from 'calypso/state/media/thunks'; import Iframe from './iframe'; -import type { CartData } from 'calypso/client/blocks/editor-checkout-modal/types'; +import { RequestCart } from '@automattic/shopping-cart'; /** * Types @@ -94,7 +94,7 @@ interface State { multiple?: any; postUrl?: T.URL; previewUrl: T.URL; - cartData?: CartData; + cartData?: RequestCart; } /* eslint-enable @typescript-eslint/no-explicit-any */ From dfbe2370bd7c5e0689b28a48450b5952659517fc Mon Sep 17 00:00:00 2001 From: Tom Cafferkey Date: Thu, 29 Oct 2020 15:23:41 +0000 Subject: [PATCH 4/4] Add type to import statement of RequestCart interface from `@automattic/shopping-cart` --- client/gutenberg/editor/calypsoify-iframe.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/editor/calypsoify-iframe.tsx b/client/gutenberg/editor/calypsoify-iframe.tsx index 4b148fd9283f8..f18d85758fd03 100644 --- a/client/gutenberg/editor/calypsoify-iframe.tsx +++ b/client/gutenberg/editor/calypsoify-iframe.tsx @@ -56,7 +56,7 @@ import { REASON_BLOCK_EDITOR_UNKOWN_IFRAME_LOAD_FAILURE } from 'calypso/state/de import { setMediaLibrarySelectedItems } from 'calypso/state/media/actions'; import { fetchMediaItem, getMediaItem } from 'calypso/state/media/thunks'; import Iframe from './iframe'; -import { RequestCart } from '@automattic/shopping-cart'; +import type { RequestCart } from '@automattic/shopping-cart'; /** * Types