From 9f80daa46a4e590470b0fedb0681681250562858 Mon Sep 17 00:00:00 2001 From: Renato Augusto Gama dos Santos Date: Fri, 2 Dec 2022 13:18:42 -0300 Subject: [PATCH] My Jetpack: Requires/Push to connection only if needed (#27615) --- .../connected-product-card/index.jsx | 20 +++++--- .../components/product-detail-card/index.jsx | 47 +++++++++++-------- .../components/product-interstitial/index.jsx | 6 +-- ...ate-my-jetpack-activate-while-disconnected | 4 ++ .../my-jetpack/src/class-wpcom-products.php | 41 +++++++++++----- 5 files changed, 75 insertions(+), 43 deletions(-) create mode 100644 projects/packages/my-jetpack/changelog/update-my-jetpack-activate-while-disconnected diff --git a/projects/packages/my-jetpack/_inc/components/connected-product-card/index.jsx b/projects/packages/my-jetpack/_inc/components/connected-product-card/index.jsx index a4b7b03b9c7e4..40626211dea4c 100644 --- a/projects/packages/my-jetpack/_inc/components/connected-product-card/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/connected-product-card/index.jsx @@ -9,7 +9,7 @@ import ProductCard from '../product-card'; const ConnectedProductCard = ( { admin, slug } ) => { const { isRegistered, isUserConnected } = useConnection(); const { detail, status, activate, deactivate, isFetching } = useProduct( slug ); - const { name, description, manageUrl } = detail; + const { name, description, manageUrl, requiresUserConnection } = detail; const navigateToConnectionPage = useMyJetpackNavigate( '/connection' ); @@ -25,14 +25,20 @@ const ConnectedProductCard = ( { admin, slug } ) => { /* * Redirect only if connected */ - const callOnlyIfAllowed = callback => () => { - if ( ! isRegistered || ! isUserConnected ) { + const handleActivate = useCallback( () => { + if ( ( ! isRegistered || ! isUserConnected ) && requiresUserConnection ) { navigateToConnectionPage(); return; } - callback(); - }; + activate(); + }, [ + activate, + isRegistered, + isUserConnected, + requiresUserConnection, + navigateToConnectionPage, + ] ); const Icon = getIconBySlug( slug ); @@ -46,8 +52,8 @@ const ConnectedProductCard = ( { admin, slug } ) => { isFetching={ isFetching } onDeactivate={ deactivate } slug={ slug } - onActivate={ activate } - onAdd={ callOnlyIfAllowed( navigateToAddProductPage ) } + onActivate={ handleActivate } + onAdd={ navigateToAddProductPage } onManage={ onManage } onFixConnection={ navigateToConnectionPage } /> diff --git a/projects/packages/my-jetpack/_inc/components/product-detail-card/index.jsx b/projects/packages/my-jetpack/_inc/components/product-detail-card/index.jsx index 1458479b53324..8916ef667f4a9 100644 --- a/projects/packages/my-jetpack/_inc/components/product-detail-card/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-detail-card/index.jsx @@ -10,15 +10,14 @@ import { H3, Alert, } from '@automattic/jetpack-components'; +import { useProductCheckoutWorkflow } from '@automattic/jetpack-connection'; import { ExternalLink } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { Icon, check, plus } from '@wordpress/icons'; import classnames from 'classnames'; import React, { useCallback } from 'react'; import useAnalytics from '../../hooks/use-analytics'; -import useMyJetpackConnection from '../../hooks/use-my-jetpack-connection'; import { useProduct } from '../../hooks/use-product'; -import getProductCheckoutUrl from '../../utils/get-product-checkout-url'; import ProductDetailButton from '../product-detail-button'; import styles from './style.module.scss'; @@ -67,7 +66,8 @@ function Price( { value, currency, isOld } ) { * @returns {object} ProductDetailCard react component. */ const ProductDetailCard = ( { slug, onClick, trackButtonClick, className, supportingInfo } ) => { - const fileSystemWriteAccess = window?.myJetpackInitialState?.fileSystemWriteAccess; + const { fileSystemWriteAccess, siteSuffix, myJetpackUrl } = window?.myJetpackInitialState ?? {}; + const { detail, isFetching } = useProduct( slug ); const { title, @@ -93,7 +93,6 @@ const ProductDetailCard = ( { slug, onClick, trackButtonClick, className, suppor wpcomProductSlug, wpcomFreeProductSlug, } = pricingForUi; - const { isUserConnected } = useMyJetpackConnection(); const { recordEvent } = useAnalytics(); @@ -104,15 +103,25 @@ const ProductDetailCard = ( { slug, onClick, trackButtonClick, className, suppor */ const needsPurchase = ! isFree && ! hasRequiredPlan; - const addProductUrl = - needsPurchase && wpcomProductSlug - ? getProductCheckoutUrl( wpcomProductSlug, isUserConnected ) // @ToDo: Remove this when we have a new product structure. - : null; + const { + run: mainCheckoutRedirect, + hasCheckoutStarted: hasMainCheckoutStarted, + } = useProductCheckoutWorkflow( { + productSlug: wpcomProductSlug, + redirectUrl: myJetpackUrl, + siteSuffix, + from: 'my-jetpack', + } ); - const addFreeProductUrl = - trialAvailable && wpcomFreeProductSlug - ? getProductCheckoutUrl( wpcomFreeProductSlug, isUserConnected ) // @ToDo: Remove this when we have a new product structure. - : null; + const { + run: trialCheckoutRedirect, + hasCheckoutStarted: hasTrialCheckoutStarted, + } = useProductCheckoutWorkflow( { + productSlug: wpcomFreeProductSlug, + redirectUrl: myJetpackUrl, + siteSuffix, + from: 'my-jetpack', + } ); // Suppported products icons. const icons = isBundle @@ -138,13 +147,13 @@ const ProductDetailCard = ( { slug, onClick, trackButtonClick, className, suppor const clickHandler = useCallback( () => { trackButtonClick(); - onClick?.( addProductUrl ); - }, [ onClick, trackButtonClick, addProductUrl ] ); + onClick?.( mainCheckoutRedirect ); + }, [ onClick, trackButtonClick, mainCheckoutRedirect ] ); const trialClickHandler = useCallback( () => { trackButtonClick( wpcomFreeProductSlug ); - onClick?.( addFreeProductUrl ); - }, [ onClick, trackButtonClick, addFreeProductUrl, wpcomFreeProductSlug ] ); + onClick?.( trialCheckoutRedirect ); + }, [ onClick, trackButtonClick, trialCheckoutRedirect, wpcomFreeProductSlug ] ); const disclaimerClickHandler = useCallback( id => { @@ -246,10 +255,9 @@ const ProductDetailCard = ( { slug, onClick, trackButtonClick, className, suppor @@ -264,10 +272,9 @@ const ProductDetailCard = ( { slug, onClick, trackButtonClick, className, suppor diff --git a/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx b/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx index 0559f5b706be9..cf2dce1b08f07 100644 --- a/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/product-interstitial/index.jsx @@ -58,7 +58,7 @@ export default function ProductInterstitial( { const navigateToMyJetpackOverviewPage = useMyJetpackNavigate( '/' ); const clickHandler = useCallback( - checkoutUrl => { + checkout => { activate().finally( () => { const product = select( STORE_ID ).getProduct( slug ); const postActivationUrl = product?.postActivationUrl; @@ -71,12 +71,12 @@ export default function ProductInterstitial( { return; } - if ( ! needsPurchase || ! checkoutUrl ) { + if ( ! needsPurchase ) { return navigateToMyJetpackOverviewPage(); } // Redirect to the checkout page. - window.location.href = checkoutUrl; + checkout?.(); } ); }, [ navigateToMyJetpackOverviewPage, activate, slug ] diff --git a/projects/packages/my-jetpack/changelog/update-my-jetpack-activate-while-disconnected b/projects/packages/my-jetpack/changelog/update-my-jetpack-activate-while-disconnected new file mode 100644 index 0000000000000..90e63bcd604e9 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/update-my-jetpack-activate-while-disconnected @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +My Jetpack: Requires connection only if needed diff --git a/projects/packages/my-jetpack/src/class-wpcom-products.php b/projects/packages/my-jetpack/src/class-wpcom-products.php index 7611d94590fb0..81b4cab7a3769 100644 --- a/projects/packages/my-jetpack/src/class-wpcom-products.php +++ b/projects/packages/my-jetpack/src/class-wpcom-products.php @@ -35,21 +35,36 @@ class Wpcom_Products { * @return Object|WP_Error */ private static function get_products_from_wpcom() { - - $blog_id = \Jetpack_Options::get_option( 'id' ); - $endpoint = sprintf( '/sites/%d/products/?_locale=%s&type=jetpack', $blog_id, get_user_locale() ); - - $wpcom_request = Client::wpcom_json_api_request_as_blog( - $endpoint, - '1.1', - array( - 'method' => 'GET', - 'headers' => array( - 'X-Forwarded-For' => ( new Visitor() )->get_ip( true ), - ), - ) + $blog_id = \Jetpack_Options::get_option( 'id' ); + $ip = ( new Visitor() )->get_ip( true ); + $headers = array( + 'X-Forwarded-For' => $ip, ); + // If has a blog id, use connected endpoint. + + if ( $blog_id ) { + $endpoint = sprintf( '/sites/%d/products/?_locale=%s&type=jetpack', $blog_id, get_user_locale() ); + + $wpcom_request = Client::wpcom_json_api_request_as_blog( + $endpoint, + '1.1', + array( + 'method' => 'GET', + 'headers' => $headers, + ) + ); + } else { + $endpoint = 'https://public-api.wordpress.com/rest/v1.1/products?locale=' . get_user_locale() . '&type=jetpack'; + + $wpcom_request = wp_remote_get( + esc_url_raw( $endpoint ), + array( + 'headers' => $headers, + ) + ); + } + $response_code = wp_remote_retrieve_response_code( $wpcom_request ); if ( 200 === $response_code ) {