From e69a2c5ba4551d592cdc765920228bb1ea729f3e Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:39:30 +1000 Subject: [PATCH 01/12] My Jetpack: Refresh product list after connecting --- .../components/my-jetpack-screen/index.jsx | 2 +- .../product-cards-section/index.tsx | 31 ++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx b/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx index 7885e276023cb..e6d7223530c92 100644 --- a/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx @@ -167,7 +167,7 @@ export default function MyJetpackScreen() { ) } { isSectionVisible && } - + { jetpackManage.isEnabled && ( diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index be198ae05a8da..87cd7bf7d73da 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -1,6 +1,6 @@ import { Container, Col, Text, AdminSectionHero } from '@automattic/jetpack-components'; import { __ } from '@wordpress/i18n'; -import { useMemo } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { PRODUCT_SLUGS } from '../../data/constants'; import { getMyJetpackWindowInitialState } from '../../data/utils/get-my-jetpack-window-state'; import StatsSection from '../stats-section'; @@ -90,17 +90,32 @@ const DisplayItems: FC< DisplayItemsProps > = ( { slugs } ) => { interface ProductCardsSectionProps { noticeMessage: ReactNode; + siteIsRegistered?: boolean; } -const ProductCardsSection: FC< ProductCardsSectionProps > = ( { noticeMessage } ) => { - const { ownedProducts = [], unownedProducts = [] } = - getMyJetpackWindowInitialState( 'lifecycleStats' ); +const ProductCardsSection: FC< ProductCardsSectionProps > = ( { + noticeMessage, + siteIsRegistered, +} ) => { + const [ siteOwnedProducts, setSiteOwnedProducts ] = useState< JetpackModule[] >( [] ); + const [ siteUnownedProducts, setSiteUnownedProducts ] = useState< JetpackModule[] >( [] ); + + const getProducts = () => { + const { ownedProducts = [], unownedProducts = [] } = + getMyJetpackWindowInitialState( 'lifecycleStats' ); + setSiteOwnedProducts( ownedProducts ); + setSiteUnownedProducts( unownedProducts ); + }; + + useEffect( () => { + getProducts(); + }, [ siteIsRegistered ] ); const unownedSectionTitle = useMemo( () => { - return ownedProducts.length > 0 + return siteOwnedProducts.length > 0 ? __( 'Discover more', 'jetpack-my-jetpack' ) : __( 'Discover all Jetpack Products', 'jetpack-my-jetpack' ); - }, [ ownedProducts.length ] ); + }, [ siteOwnedProducts.length ] ); const filterProducts = ( products: JetpackModule[] ) => { return products.filter( product => { @@ -111,8 +126,8 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { noticeMessage } } ); }; - const filteredOwnedProducts = filterProducts( ownedProducts ); - const filteredUnownedProducts = filterProducts( unownedProducts ); + const filteredOwnedProducts = filterProducts( siteOwnedProducts ); + const filteredUnownedProducts = filterProducts( siteUnownedProducts ); return ( <> From 1cb9e96a1215e33ec591a1f77c229017f18dcac6 Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Wed, 11 Sep 2024 15:41:40 +1000 Subject: [PATCH 02/12] changelog --- .../my-jetpack/changelog/myjetpack-connected-products | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 projects/packages/my-jetpack/changelog/myjetpack-connected-products diff --git a/projects/packages/my-jetpack/changelog/myjetpack-connected-products b/projects/packages/my-jetpack/changelog/myjetpack-connected-products new file mode 100644 index 0000000000000..94309db11c9d7 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/myjetpack-connected-products @@ -0,0 +1,5 @@ +Significance: patch +Type: fixed +Comment: The fix is updating product list after connecting Jetpack, without reloading the page. + + From 495c1ee17cd73ab4fb9d0f058114fb0f7bb67bbe Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:03:42 +1000 Subject: [PATCH 03/12] My Jetpack: Addin new endpoint to get products by ownership status --- .../product-cards-section/index.tsx | 4 ++ .../my-jetpack/_inc/data/constants.ts | 2 + .../products/use-products-by-ownership.ts | 42 +++++++++++++++++++ .../my-jetpack/src/class-rest-products.php | 31 ++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index 87cd7bf7d73da..cefcbe45e0548 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -2,6 +2,7 @@ import { Container, Col, Text, AdminSectionHero } from '@automattic/jetpack-comp import { __ } from '@wordpress/i18n'; import { useEffect, useMemo, useState } from 'react'; import { PRODUCT_SLUGS } from '../../data/constants'; +import useProductsByOwnership from '../../data/products/use-products-by-ownership'; import { getMyJetpackWindowInitialState } from '../../data/utils/get-my-jetpack-window-state'; import StatsSection from '../stats-section'; import AiCard from './ai-card'; @@ -100,6 +101,9 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { const [ siteOwnedProducts, setSiteOwnedProducts ] = useState< JetpackModule[] >( [] ); const [ siteUnownedProducts, setSiteUnownedProducts ] = useState< JetpackModule[] >( [] ); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { products: productsData, isLoading } = useProductsByOwnership(); + const getProducts = () => { const { ownedProducts = [], unownedProducts = [] } = getMyJetpackWindowInitialState( 'lifecycleStats' ); diff --git a/projects/packages/my-jetpack/_inc/data/constants.ts b/projects/packages/my-jetpack/_inc/data/constants.ts index 2f09c4c96707f..d61e8cafe4edc 100644 --- a/projects/packages/my-jetpack/_inc/data/constants.ts +++ b/projects/packages/my-jetpack/_inc/data/constants.ts @@ -8,6 +8,7 @@ export const REST_API_COUNT_BACKUP_ITEMS_ENDPOINT = `${ REST_API_NAMESPACE }/sit export const REST_API_CHAT_AVAILABILITY_ENDPOINT = `${ REST_API_NAMESPACE }/chat/availability`; export const REST_API_CHAT_AUTHENTICATION_ENDPOINT = `${ REST_API_NAMESPACE }/chat/authentication`; export const REST_API_SITE_PRODUCTS_ENDPOINT = `${ REST_API_NAMESPACE }/site/products`; +export const REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT = `${ REST_API_NAMESPACE }/site/products/ownership`; export const REST_API_VIDEOPRESS_FEATURED_STATS = 'videopress/v1/stats/featured'; export const REST_API_SITE_DISMISS_BANNER = `${ REST_API_NAMESPACE }/site/dismiss-welcome-banner`; export const REST_API_EVALUATE_SITE_RECOMMENDATIONS = `${ REST_API_NAMESPACE }/site/recommendations/evaluation`; @@ -18,6 +19,7 @@ export const getStatsHighlightsEndpoint = ( blogId: string ) => // Query names export const QUERY_PRODUCT_KEY = 'product'; +export const QUERY_PRODUCT_BY_OWNERSHIP_KEY = 'product ownership'; export const QUERY_ACTIVATE_PRODUCT_KEY = 'activate product'; export const QUERY_INSTALL_PRODUCT_KEY = 'install product'; export const QUERY_VIDEOPRESS_STATS_KEY = 'videopress stats'; diff --git a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts new file mode 100644 index 0000000000000..e1f47c93daf07 --- /dev/null +++ b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts @@ -0,0 +1,42 @@ +import { REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT } from '../constants'; +import { QUERY_PRODUCT_BY_OWNERSHIP_KEY } from '../constants'; +import useSimpleQuery from '../use-simple-query'; +// import { getMyJetpackWindowInitialState } from '../utils/get-my-jetpack-window-state'; +import type { ProductSnakeCase } from '../types'; +// import type { RefetchOptions, QueryObserverResult } from '@tanstack/react-query'; + +// Create query to fetch new product data from the server +const useFetchProductsByOwnership = () => { + const queryResult = useSimpleQuery< ProductSnakeCase >( { + name: `${ QUERY_PRODUCT_BY_OWNERSHIP_KEY }`, + query: { + path: REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT, + }, + } ); + + return queryResult; +}; + +// Fetch the product data from the server and update the global state +// const refetchProduct = async ( +// productId: string, +// refetch: ( +// options?: RefetchOptions +// ) => Promise< QueryObserverResult< ProductSnakeCase, WP_Error > > +// ) => { +// const { data: refetchedProduct } = await refetch(); + +// window.myJetpackInitialState.products.items[ productId ] = refetchedProduct; +// }; + +const useProductsByOwnership = () => { + const { data, isLoading } = useFetchProductsByOwnership(); + + return { + // refetch: useCallback( () => refetchProduct( productId, refetch ), [ productId, refetch ] ), + products: data, //TODO: either pass products or update the windows opbject like refetchProduct + isLoading, + }; +}; + +export default useProductsByOwnership; diff --git a/projects/packages/my-jetpack/src/class-rest-products.php b/projects/packages/my-jetpack/src/class-rest-products.php index cb253ce1625f6..66856443a0d21 100644 --- a/projects/packages/my-jetpack/src/class-rest-products.php +++ b/projects/packages/my-jetpack/src/class-rest-products.php @@ -83,6 +83,27 @@ public function __construct() { ), ) ); + + register_rest_route( + 'my-jetpack/v1', + 'site/products/ownership', + array( + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => __CLASS__ . '::get_products_by_ownership', + 'permission_callback' => __CLASS__ . '::permissions_callback', + ), + 'schema' => array( $this, 'get_products_schema' ), + ) + ); + + $product_arg = array( + 'description' => __( 'Product slug', 'jetpack-my-jetpack' ), + 'type' => 'string', + 'enum' => Products::get_products_by_ownership(), + 'required' => true, + 'validate_callback' => __CLASS__ . '::check_product_argument', + ); } /** @@ -142,6 +163,16 @@ public static function get_products() { return rest_ensure_response( $response, 200 ); } + /** + * Site products endpoint. + * + * @return array of site products list. + */ + public static function get_products_by_ownership() { + $response = Products::get_products_by_ownership(); + return rest_ensure_response( $response, 200 ); + } + /** * Site single product endpoint. * From 934b91b958bd8445c80fb23170429d5dd2b3c07b Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:30:41 +1000 Subject: [PATCH 04/12] My Jetpack: Updating ownership endpoint implementation and handling --- .../product-cards-section/index.tsx | 26 +++++++++---------- .../my-jetpack/_inc/data/constants.ts | 2 +- .../products/use-products-by-ownership.ts | 7 ++--- .../my-jetpack/src/class-rest-products.php | 18 ++++--------- 4 files changed, 23 insertions(+), 30 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index cefcbe45e0548..96306046fe0d5 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -98,22 +98,22 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { noticeMessage, siteIsRegistered, } ) => { - const [ siteOwnedProducts, setSiteOwnedProducts ] = useState< JetpackModule[] >( [] ); - const [ siteUnownedProducts, setSiteUnownedProducts ] = useState< JetpackModule[] >( [] ); + const { ownedProducts: inntialOwnedProducts = [], unownedProducts: inntialUnownedProducts = [] } = + getMyJetpackWindowInitialState( 'lifecycleStats' ); + const [ siteOwnedProducts, setSiteOwnedProducts ] = + useState< JetpackModule[] >( inntialOwnedProducts ); + const [ siteUnownedProducts, setSiteUnownedProducts ] = + useState< JetpackModule[] >( inntialUnownedProducts ); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { products: productsData, isLoading } = useProductsByOwnership(); - - const getProducts = () => { - const { ownedProducts = [], unownedProducts = [] } = - getMyJetpackWindowInitialState( 'lifecycleStats' ); - setSiteOwnedProducts( ownedProducts ); - setSiteUnownedProducts( unownedProducts ); - }; + const { data: productOwnershipData, isLoading } = useProductsByOwnership(); useEffect( () => { - getProducts(); - }, [ siteIsRegistered ] ); + if ( ! isLoading ) { + const { ownedProducts = [], unownedProducts = [] } = productOwnershipData; + setSiteOwnedProducts( ownedProducts ); + setSiteUnownedProducts( unownedProducts ); + } + }, [ siteIsRegistered, productOwnershipData, isLoading ] ); const unownedSectionTitle = useMemo( () => { return siteOwnedProducts.length > 0 diff --git a/projects/packages/my-jetpack/_inc/data/constants.ts b/projects/packages/my-jetpack/_inc/data/constants.ts index d61e8cafe4edc..5d239c27c25c3 100644 --- a/projects/packages/my-jetpack/_inc/data/constants.ts +++ b/projects/packages/my-jetpack/_inc/data/constants.ts @@ -8,7 +8,7 @@ export const REST_API_COUNT_BACKUP_ITEMS_ENDPOINT = `${ REST_API_NAMESPACE }/sit export const REST_API_CHAT_AVAILABILITY_ENDPOINT = `${ REST_API_NAMESPACE }/chat/availability`; export const REST_API_CHAT_AUTHENTICATION_ENDPOINT = `${ REST_API_NAMESPACE }/chat/authentication`; export const REST_API_SITE_PRODUCTS_ENDPOINT = `${ REST_API_NAMESPACE }/site/products`; -export const REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT = `${ REST_API_NAMESPACE }/site/products/ownership`; +export const REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT = `${ REST_API_NAMESPACE }/site/ownership/products`; export const REST_API_VIDEOPRESS_FEATURED_STATS = 'videopress/v1/stats/featured'; export const REST_API_SITE_DISMISS_BANNER = `${ REST_API_NAMESPACE }/site/dismiss-welcome-banner`; export const REST_API_EVALUATE_SITE_RECOMMENDATIONS = `${ REST_API_NAMESPACE }/site/recommendations/evaluation`; diff --git a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts index e1f47c93daf07..8bb25274b92a3 100644 --- a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts +++ b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts @@ -2,12 +2,13 @@ import { REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT } from '../constants'; import { QUERY_PRODUCT_BY_OWNERSHIP_KEY } from '../constants'; import useSimpleQuery from '../use-simple-query'; // import { getMyJetpackWindowInitialState } from '../utils/get-my-jetpack-window-state'; -import type { ProductSnakeCase } from '../types'; // import type { RefetchOptions, QueryObserverResult } from '@tanstack/react-query'; // Create query to fetch new product data from the server const useFetchProductsByOwnership = () => { - const queryResult = useSimpleQuery< ProductSnakeCase >( { + const queryResult = useSimpleQuery< + Record< 'ownedProducts' | 'unownedProducts', JetpackModule[] > + >( { name: `${ QUERY_PRODUCT_BY_OWNERSHIP_KEY }`, query: { path: REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT, @@ -34,7 +35,7 @@ const useProductsByOwnership = () => { return { // refetch: useCallback( () => refetchProduct( productId, refetch ), [ productId, refetch ] ), - products: data, //TODO: either pass products or update the windows opbject like refetchProduct + data, isLoading, }; }; diff --git a/projects/packages/my-jetpack/src/class-rest-products.php b/projects/packages/my-jetpack/src/class-rest-products.php index 66856443a0d21..76e4b73a7fda4 100644 --- a/projects/packages/my-jetpack/src/class-rest-products.php +++ b/projects/packages/my-jetpack/src/class-rest-products.php @@ -77,16 +77,13 @@ public function __construct() { 'methods' => \WP_REST_Server::EDITABLE, 'callback' => __CLASS__ . '::install_standalone', 'permission_callback' => __CLASS__ . '::edit_permissions_callback', - 'args' => array( - 'product' => $product_arg, - ), ), ) ); register_rest_route( 'my-jetpack/v1', - 'site/products/ownership', + 'site/ownership/products', array( array( 'methods' => \WP_REST_Server::READABLE, @@ -96,14 +93,6 @@ public function __construct() { 'schema' => array( $this, 'get_products_schema' ), ) ); - - $product_arg = array( - 'description' => __( 'Product slug', 'jetpack-my-jetpack' ), - 'type' => 'string', - 'enum' => Products::get_products_by_ownership(), - 'required' => true, - 'validate_callback' => __CLASS__ . '::check_product_argument', - ); } /** @@ -169,7 +158,10 @@ public static function get_products() { * @return array of site products list. */ public static function get_products_by_ownership() { - $response = Products::get_products_by_ownership(); + $response = array( + 'unownedProducts' => Products::get_products_by_ownership( 'unowned' ), + 'ownedProducts' => Products::get_products_by_ownership( 'owned' ), + ); return rest_ensure_response( $response, 200 ); } From 54c1c6a82aaeda7ecfe00c0078bf20b7c285fea0 Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:42:19 +1000 Subject: [PATCH 05/12] My Jetpack: Updating ownership endpoint with refetch --- .../product-cards-section/index.tsx | 10 ++++++-- .../products/use-products-by-ownership.ts | 25 +++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index 96306046fe0d5..a4a836477d799 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -105,15 +105,21 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { const [ siteUnownedProducts, setSiteUnownedProducts ] = useState< JetpackModule[] >( inntialUnownedProducts ); - const { data: productOwnershipData, isLoading } = useProductsByOwnership(); + const { + data: productOwnershipData, + isLoading, + refetch: refetchOwnershipData, + } = useProductsByOwnership(); useEffect( () => { + refetchOwnershipData(); + if ( ! isLoading ) { const { ownedProducts = [], unownedProducts = [] } = productOwnershipData; setSiteOwnedProducts( ownedProducts ); setSiteUnownedProducts( unownedProducts ); } - }, [ siteIsRegistered, productOwnershipData, isLoading ] ); + }, [ siteIsRegistered, productOwnershipData, isLoading, refetchOwnershipData ] ); const unownedSectionTitle = useMemo( () => { return siteOwnedProducts.length > 0 diff --git a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts index 8bb25274b92a3..daad3fb0c62cf 100644 --- a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts +++ b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts @@ -1,8 +1,8 @@ +import { useCallback } from 'react'; import { REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT } from '../constants'; import { QUERY_PRODUCT_BY_OWNERSHIP_KEY } from '../constants'; import useSimpleQuery from '../use-simple-query'; -// import { getMyJetpackWindowInitialState } from '../utils/get-my-jetpack-window-state'; -// import type { RefetchOptions, QueryObserverResult } from '@tanstack/react-query'; +import type { QueryObserverResult } from '@tanstack/react-query'; // Create query to fetch new product data from the server const useFetchProductsByOwnership = () => { @@ -19,22 +19,21 @@ const useFetchProductsByOwnership = () => { }; // Fetch the product data from the server and update the global state -// const refetchProduct = async ( -// productId: string, -// refetch: ( -// options?: RefetchOptions -// ) => Promise< QueryObserverResult< ProductSnakeCase, WP_Error > > -// ) => { -// const { data: refetchedProduct } = await refetch(); +const refetchProduct = async ( + refetch: () => Promise< + QueryObserverResult< Record< 'ownedProducts' | 'unownedProducts', JetpackModule[] >, WP_Error > + > +) => { + const { data: refetchedProduct } = await refetch(); -// window.myJetpackInitialState.products.items[ productId ] = refetchedProduct; -// }; + return refetchedProduct; +}; const useProductsByOwnership = () => { - const { data, isLoading } = useFetchProductsByOwnership(); + const { data, refetch, isLoading } = useFetchProductsByOwnership(); return { - // refetch: useCallback( () => refetchProduct( productId, refetch ), [ productId, refetch ] ), + refetch: useCallback( () => refetchProduct( refetch ), [ refetch ] ), data, isLoading, }; From ef2f7ebcc584ec3a3e4397196282eb8d78db2210 Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:10:23 +1000 Subject: [PATCH 06/12] My Jetpack: Using valueStore for ownership info --- .../product-cards-section/index.tsx | 24 ++++++++++++++----- .../context/value-store/valueStoreContext.tsx | 2 ++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index a4a836477d799..40cd2391283ba 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -1,6 +1,7 @@ import { Container, Col, Text, AdminSectionHero } from '@automattic/jetpack-components'; import { __ } from '@wordpress/i18n'; -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo } from 'react'; +import { useValueStore } from '../../context/value-store/valueStoreContext'; import { PRODUCT_SLUGS } from '../../data/constants'; import useProductsByOwnership from '../../data/products/use-products-by-ownership'; import { getMyJetpackWindowInitialState } from '../../data/utils/get-my-jetpack-window-state'; @@ -100,10 +101,14 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { } ) => { const { ownedProducts: inntialOwnedProducts = [], unownedProducts: inntialUnownedProducts = [] } = getMyJetpackWindowInitialState( 'lifecycleStats' ); - const [ siteOwnedProducts, setSiteOwnedProducts ] = - useState< JetpackModule[] >( inntialOwnedProducts ); - const [ siteUnownedProducts, setSiteUnownedProducts ] = - useState< JetpackModule[] >( inntialUnownedProducts ); + const [ siteOwnedProducts, setSiteOwnedProducts ] = useValueStore( + 'siteOwnedProducts', + inntialOwnedProducts + ); + const [ siteUnownedProducts, setSiteUnownedProducts ] = useValueStore( + 'siteUnownedProducts', + inntialUnownedProducts + ); const { data: productOwnershipData, @@ -119,7 +124,14 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { setSiteOwnedProducts( ownedProducts ); setSiteUnownedProducts( unownedProducts ); } - }, [ siteIsRegistered, productOwnershipData, isLoading, refetchOwnershipData ] ); + }, [ + siteIsRegistered, + productOwnershipData, + isLoading, + refetchOwnershipData, + setSiteOwnedProducts, + setSiteUnownedProducts, + ] ); const unownedSectionTitle = useMemo( () => { return siteOwnedProducts.length > 0 diff --git a/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx b/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx index d8902c9f2b7dc..c5f7738e5b574 100644 --- a/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx +++ b/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx @@ -6,6 +6,8 @@ type ValueStoreType = { isLoadingWelcomeFlowExperiment?: boolean; recommendedModules: JetpackModule[] | null; recommendedModulesVisible: boolean; + siteOwnedProducts: JetpackModule[]; + siteUnownedProducts: JetpackModule[]; }; type ValueStoreContextType = { From 9a54f0dccc0d81b730721839b03f9b88e706699d Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:16:29 +1000 Subject: [PATCH 07/12] Cleanup --- .../my-jetpack/_inc/data/products/use-products-by-ownership.ts | 3 ++- projects/packages/my-jetpack/src/class-rest-products.php | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts index daad3fb0c62cf..a45034aeaf98d 100644 --- a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts +++ b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts @@ -2,6 +2,7 @@ import { useCallback } from 'react'; import { REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT } from '../constants'; import { QUERY_PRODUCT_BY_OWNERSHIP_KEY } from '../constants'; import useSimpleQuery from '../use-simple-query'; +import type { WP_Error } from '../types'; import type { QueryObserverResult } from '@tanstack/react-query'; // Create query to fetch new product data from the server @@ -18,7 +19,7 @@ const useFetchProductsByOwnership = () => { return queryResult; }; -// Fetch the product data from the server and update the global state +// Fetch the product data from the server const refetchProduct = async ( refetch: () => Promise< QueryObserverResult< Record< 'ownedProducts' | 'unownedProducts', JetpackModule[] >, WP_Error > diff --git a/projects/packages/my-jetpack/src/class-rest-products.php b/projects/packages/my-jetpack/src/class-rest-products.php index 76e4b73a7fda4..54d1bf66a8be2 100644 --- a/projects/packages/my-jetpack/src/class-rest-products.php +++ b/projects/packages/my-jetpack/src/class-rest-products.php @@ -90,7 +90,6 @@ public function __construct() { 'callback' => __CLASS__ . '::get_products_by_ownership', 'permission_callback' => __CLASS__ . '::permissions_callback', ), - 'schema' => array( $this, 'get_products_schema' ), ) ); } From a923fd9a7fde54ae25df7020e74d2d313819426b Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:48:00 +1000 Subject: [PATCH 08/12] My Jetpack: Updating endpoint URL --- .../_inc/components/product-cards-section/index.tsx | 6 +++--- projects/packages/my-jetpack/_inc/data/constants.ts | 2 +- projects/packages/my-jetpack/src/class-rest-products.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index 40cd2391283ba..287c4900103c5 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -99,15 +99,15 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { noticeMessage, siteIsRegistered, } ) => { - const { ownedProducts: inntialOwnedProducts = [], unownedProducts: inntialUnownedProducts = [] } = + const { ownedProducts: initialOwnedProducts = [], unownedProducts: initialUnownedProducts = [] } = getMyJetpackWindowInitialState( 'lifecycleStats' ); const [ siteOwnedProducts, setSiteOwnedProducts ] = useValueStore( 'siteOwnedProducts', - inntialOwnedProducts + initialOwnedProducts ); const [ siteUnownedProducts, setSiteUnownedProducts ] = useValueStore( 'siteUnownedProducts', - inntialUnownedProducts + initialUnownedProducts ); const { diff --git a/projects/packages/my-jetpack/_inc/data/constants.ts b/projects/packages/my-jetpack/_inc/data/constants.ts index 5d239c27c25c3..c11217819409d 100644 --- a/projects/packages/my-jetpack/_inc/data/constants.ts +++ b/projects/packages/my-jetpack/_inc/data/constants.ts @@ -8,7 +8,7 @@ export const REST_API_COUNT_BACKUP_ITEMS_ENDPOINT = `${ REST_API_NAMESPACE }/sit export const REST_API_CHAT_AVAILABILITY_ENDPOINT = `${ REST_API_NAMESPACE }/chat/availability`; export const REST_API_CHAT_AUTHENTICATION_ENDPOINT = `${ REST_API_NAMESPACE }/chat/authentication`; export const REST_API_SITE_PRODUCTS_ENDPOINT = `${ REST_API_NAMESPACE }/site/products`; -export const REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT = `${ REST_API_NAMESPACE }/site/ownership/products`; +export const REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT = `${ REST_API_NAMESPACE }/site/products-ownership`; export const REST_API_VIDEOPRESS_FEATURED_STATS = 'videopress/v1/stats/featured'; export const REST_API_SITE_DISMISS_BANNER = `${ REST_API_NAMESPACE }/site/dismiss-welcome-banner`; export const REST_API_EVALUATE_SITE_RECOMMENDATIONS = `${ REST_API_NAMESPACE }/site/recommendations/evaluation`; diff --git a/projects/packages/my-jetpack/src/class-rest-products.php b/projects/packages/my-jetpack/src/class-rest-products.php index 54d1bf66a8be2..dfa60108b7c56 100644 --- a/projects/packages/my-jetpack/src/class-rest-products.php +++ b/projects/packages/my-jetpack/src/class-rest-products.php @@ -83,7 +83,7 @@ public function __construct() { register_rest_route( 'my-jetpack/v1', - 'site/ownership/products', + 'site/products-ownership', array( array( 'methods' => \WP_REST_Server::READABLE, From 73083d987ae91eefa3544ef554f9d626a13b6845 Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:26:56 +1000 Subject: [PATCH 09/12] My Jetpack: Updating structure for stored product ownership --- .../product-cards-section/index.tsx | 33 +++++++++---------- .../context/value-store/valueStoreContext.tsx | 6 ++-- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index 287c4900103c5..7ce1fedf9598c 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -101,14 +101,10 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { } ) => { const { ownedProducts: initialOwnedProducts = [], unownedProducts: initialUnownedProducts = [] } = getMyJetpackWindowInitialState( 'lifecycleStats' ); - const [ siteOwnedProducts, setSiteOwnedProducts ] = useValueStore( - 'siteOwnedProducts', - initialOwnedProducts - ); - const [ siteUnownedProducts, setSiteUnownedProducts ] = useValueStore( - 'siteUnownedProducts', - initialUnownedProducts - ); + const [ productsOwnership, setProductsOwnership ] = useValueStore( 'productsOwnership', { + ownedProducts: initialOwnedProducts, + unownedProducts: initialUnownedProducts, + } ); const { data: productOwnershipData, @@ -117,27 +113,28 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { } = useProductsByOwnership(); useEffect( () => { - refetchOwnershipData(); - if ( ! isLoading ) { + if ( siteIsRegistered ) { + refetchOwnershipData(); + } + const { ownedProducts = [], unownedProducts = [] } = productOwnershipData; - setSiteOwnedProducts( ownedProducts ); - setSiteUnownedProducts( unownedProducts ); + setProductsOwnership( { ownedProducts, unownedProducts } ); } }, [ siteIsRegistered, productOwnershipData, isLoading, refetchOwnershipData, - setSiteOwnedProducts, - setSiteUnownedProducts, + productsOwnership, + setProductsOwnership, ] ); const unownedSectionTitle = useMemo( () => { - return siteOwnedProducts.length > 0 + return productsOwnership.ownedProducts.length > 0 ? __( 'Discover more', 'jetpack-my-jetpack' ) : __( 'Discover all Jetpack Products', 'jetpack-my-jetpack' ); - }, [ siteOwnedProducts.length ] ); + }, [ productsOwnership.ownedProducts.length ] ); const filterProducts = ( products: JetpackModule[] ) => { return products.filter( product => { @@ -148,8 +145,8 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { } ); }; - const filteredOwnedProducts = filterProducts( siteOwnedProducts ); - const filteredUnownedProducts = filterProducts( siteUnownedProducts ); + const filteredOwnedProducts = filterProducts( productsOwnership.ownedProducts ); + const filteredUnownedProducts = filterProducts( productsOwnership.unownedProducts ); return ( <> diff --git a/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx b/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx index c5f7738e5b574..0774e0aadeca6 100644 --- a/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx +++ b/projects/packages/my-jetpack/_inc/context/value-store/valueStoreContext.tsx @@ -6,8 +6,10 @@ type ValueStoreType = { isLoadingWelcomeFlowExperiment?: boolean; recommendedModules: JetpackModule[] | null; recommendedModulesVisible: boolean; - siteOwnedProducts: JetpackModule[]; - siteUnownedProducts: JetpackModule[]; + productsOwnership: { + ownedProducts: JetpackModule[]; + unownedProducts: JetpackModule[]; + }; }; type ValueStoreContextType = { From e8e69cc2c8cdf7151282325f365ba39b2d7a3be9 Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:34:47 +1000 Subject: [PATCH 10/12] My Jetpack: Typo fix --- .../my-jetpack/_inc/components/product-cards-section/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index 7ce1fedf9598c..9f3f5728190d9 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -126,7 +126,6 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { productOwnershipData, isLoading, refetchOwnershipData, - productsOwnership, setProductsOwnership, ] ); From 681284a8fafb58d40a9f28e47b55fe0aa71b9c91 Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:43:55 +1000 Subject: [PATCH 11/12] My Jetpack: Review updates --- .../product-cards-section/index.tsx | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index 9f3f5728190d9..5e8d0c4c70545 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -99,12 +99,13 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { noticeMessage, siteIsRegistered, } ) => { - const { ownedProducts: initialOwnedProducts = [], unownedProducts: initialUnownedProducts = [] } = - getMyJetpackWindowInitialState( 'lifecycleStats' ); - const [ productsOwnership, setProductsOwnership ] = useValueStore( 'productsOwnership', { - ownedProducts: initialOwnedProducts, - unownedProducts: initialUnownedProducts, - } ); + const [ { ownedProducts, unownedProducts }, setProductsOwnership ] = useValueStore( + 'productsOwnership', + { + ownedProducts: getMyJetpackWindowInitialState( 'lifecycleStats' )?.ownedProducts ?? [], + unownedProducts: getMyJetpackWindowInitialState( 'lifecycleStats' )?.unownedProducts ?? [], + } + ); const { data: productOwnershipData, @@ -113,14 +114,15 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { } = useProductsByOwnership(); useEffect( () => { - if ( ! isLoading ) { - if ( siteIsRegistered ) { - refetchOwnershipData(); - } + if ( isLoading ) { + return; + } - const { ownedProducts = [], unownedProducts = [] } = productOwnershipData; - setProductsOwnership( { ownedProducts, unownedProducts } ); + if ( siteIsRegistered ) { + refetchOwnershipData(); } + + setProductsOwnership( productOwnershipData ); }, [ siteIsRegistered, productOwnershipData, @@ -130,10 +132,10 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { ] ); const unownedSectionTitle = useMemo( () => { - return productsOwnership.ownedProducts.length > 0 + return ownedProducts.length > 0 ? __( 'Discover more', 'jetpack-my-jetpack' ) : __( 'Discover all Jetpack Products', 'jetpack-my-jetpack' ); - }, [ productsOwnership.ownedProducts.length ] ); + }, [ ownedProducts.length ] ); const filterProducts = ( products: JetpackModule[] ) => { return products.filter( product => { @@ -144,8 +146,8 @@ const ProductCardsSection: FC< ProductCardsSectionProps > = ( { } ); }; - const filteredOwnedProducts = filterProducts( productsOwnership.ownedProducts ); - const filteredUnownedProducts = filterProducts( productsOwnership.unownedProducts ); + const filteredOwnedProducts = filterProducts( ownedProducts ); + const filteredUnownedProducts = filterProducts( unownedProducts ); return ( <> From 6e8a38175d79cd5ce77fcaf45a74026c4c13290e Mon Sep 17 00:00:00 2001 From: Grzegorz Chudzinski-Pawlowski <112354940+grzegorz-cp@users.noreply.github.com> Date: Wed, 18 Sep 2024 12:15:47 +1000 Subject: [PATCH 12/12] My Jetpack: Refactoring fetching of owned products --- .../components/my-jetpack-screen/index.jsx | 2 +- .../product-cards-section/index.tsx | 39 ++----------------- .../welcome-flow/ConnectionStep.tsx | 12 +++++- .../products/use-products-by-ownership.ts | 35 +++++++++-------- .../use-site-connection-notice.tsx | 6 +++ 5 files changed, 39 insertions(+), 55 deletions(-) diff --git a/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx b/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx index e6d7223530c92..7885e276023cb 100644 --- a/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx +++ b/projects/packages/my-jetpack/_inc/components/my-jetpack-screen/index.jsx @@ -167,7 +167,7 @@ export default function MyJetpackScreen() { ) } { isSectionVisible && } - + { jetpackManage.isEnabled && ( diff --git a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx index 5e8d0c4c70545..2d6427a2258af 100644 --- a/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/product-cards-section/index.tsx @@ -1,7 +1,6 @@ import { Container, Col, Text, AdminSectionHero } from '@automattic/jetpack-components'; import { __ } from '@wordpress/i18n'; -import { useEffect, useMemo } from 'react'; -import { useValueStore } from '../../context/value-store/valueStoreContext'; +import { useMemo } from 'react'; import { PRODUCT_SLUGS } from '../../data/constants'; import useProductsByOwnership from '../../data/products/use-products-by-ownership'; import { getMyJetpackWindowInitialState } from '../../data/utils/get-my-jetpack-window-state'; @@ -92,45 +91,13 @@ const DisplayItems: FC< DisplayItemsProps > = ( { slugs } ) => { interface ProductCardsSectionProps { noticeMessage: ReactNode; - siteIsRegistered?: boolean; } -const ProductCardsSection: FC< ProductCardsSectionProps > = ( { - noticeMessage, - siteIsRegistered, -} ) => { - const [ { ownedProducts, unownedProducts }, setProductsOwnership ] = useValueStore( - 'productsOwnership', - { - ownedProducts: getMyJetpackWindowInitialState( 'lifecycleStats' )?.ownedProducts ?? [], - unownedProducts: getMyJetpackWindowInitialState( 'lifecycleStats' )?.unownedProducts ?? [], - } - ); - +const ProductCardsSection: FC< ProductCardsSectionProps > = ( { noticeMessage } ) => { const { - data: productOwnershipData, - isLoading, - refetch: refetchOwnershipData, + data: { ownedProducts, unownedProducts }, } = useProductsByOwnership(); - useEffect( () => { - if ( isLoading ) { - return; - } - - if ( siteIsRegistered ) { - refetchOwnershipData(); - } - - setProductsOwnership( productOwnershipData ); - }, [ - siteIsRegistered, - productOwnershipData, - isLoading, - refetchOwnershipData, - setProductsOwnership, - ] ); - const unownedSectionTitle = useMemo( () => { return ownedProducts.length > 0 ? __( 'Discover more', 'jetpack-my-jetpack' ) diff --git a/projects/packages/my-jetpack/_inc/components/welcome-flow/ConnectionStep.tsx b/projects/packages/my-jetpack/_inc/components/welcome-flow/ConnectionStep.tsx index ae45311131c18..3d963ff52a61d 100644 --- a/projects/packages/my-jetpack/_inc/components/welcome-flow/ConnectionStep.tsx +++ b/projects/packages/my-jetpack/_inc/components/welcome-flow/ConnectionStep.tsx @@ -4,6 +4,7 @@ import { __ } from '@wordpress/i18n'; import { useCallback, useContext } from 'react'; import { NoticeContext } from '../../context/notices/noticeContext'; import { NOTICE_SITE_CONNECTED } from '../../context/notices/noticeTemplates'; +import useProductsByOwnership from '../../data/products/use-products-by-ownership'; import useAnalytics from '../../hooks/use-analytics'; import sideloadTracks from '../../utils/side-load-tracks'; import styles from './style.module.scss'; @@ -34,6 +35,7 @@ const ConnectionStep = ( { const { setNotice, resetNotice } = useContext( NoticeContext ); const activationButtonLabel = __( 'Activate Jetpack in one click', 'jetpack-my-jetpack' ); + const { refetch: refetchOwnershipData } = useProductsByOwnership(); const onConnectSiteClick = useCallback( async () => { recordEvent( 'jetpack_myjetpack_welcome_banner_connect_site_click' ); @@ -58,10 +60,18 @@ const ConnectionStep = ( { } finally { resetNotice(); setNotice( NOTICE_SITE_CONNECTED, resetNotice ); + refetchOwnershipData(); onUpdateWelcomeFlowExperiment( state => ( { ...state, isLoading: false } ) ); } - }, [ onActivateSite, onUpdateWelcomeFlowExperiment, recordEvent, resetNotice, setNotice ] ); + }, [ + onActivateSite, + onUpdateWelcomeFlowExperiment, + recordEvent, + refetchOwnershipData, + resetNotice, + setNotice, + ] ); return ( <> diff --git a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts index a45034aeaf98d..804cf56ba285e 100644 --- a/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts +++ b/projects/packages/my-jetpack/_inc/data/products/use-products-by-ownership.ts @@ -1,9 +1,9 @@ -import { useCallback } from 'react'; -import { REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT } from '../constants'; +import { useEffect } from 'react'; +import { useValueStore } from '../../context/value-store/valueStoreContext'; +import { getMyJetpackWindowInitialState } from '../../data/utils/get-my-jetpack-window-state'; import { QUERY_PRODUCT_BY_OWNERSHIP_KEY } from '../constants'; +import { REST_API_SITE_PRODUCTS_OWNERSHIP_ENDPOINT } from '../constants'; import useSimpleQuery from '../use-simple-query'; -import type { WP_Error } from '../types'; -import type { QueryObserverResult } from '@tanstack/react-query'; // Create query to fetch new product data from the server const useFetchProductsByOwnership = () => { @@ -19,23 +19,24 @@ const useFetchProductsByOwnership = () => { return queryResult; }; -// Fetch the product data from the server -const refetchProduct = async ( - refetch: () => Promise< - QueryObserverResult< Record< 'ownedProducts' | 'unownedProducts', JetpackModule[] >, WP_Error > - > -) => { - const { data: refetchedProduct } = await refetch(); - - return refetchedProduct; -}; - const useProductsByOwnership = () => { + const [ productsOwnership, setProductsOwnership ] = useValueStore( 'productsOwnership', { + ownedProducts: getMyJetpackWindowInitialState( 'lifecycleStats' ).ownedProducts, + unownedProducts: getMyJetpackWindowInitialState( 'lifecycleStats' ).unownedProducts, + } ); + const { data, refetch, isLoading } = useFetchProductsByOwnership(); + useEffect( () => { + if ( ! isLoading && data ) { + const { ownedProducts = [], unownedProducts = [] } = data; + setProductsOwnership( { ownedProducts, unownedProducts } ); + } + }, [ data, isLoading, setProductsOwnership ] ); + return { - refetch: useCallback( () => refetchProduct( refetch ), [ refetch ] ), - data, + refetch, + data: productsOwnership, isLoading, }; }; diff --git a/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-site-connection-notice.tsx b/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-site-connection-notice.tsx index f38df9d053b02..7234d51aa341b 100644 --- a/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-site-connection-notice.tsx +++ b/projects/packages/my-jetpack/_inc/hooks/use-notification-watcher/use-site-connection-notice.tsx @@ -6,6 +6,7 @@ import { NOTICE_PRIORITY_HIGH } from '../../context/constants'; import { NoticeContext } from '../../context/notices/noticeContext'; import { NOTICE_SITE_CONNECTED } from '../../context/notices/noticeTemplates'; import { useAllProducts } from '../../data/products/use-product'; +import useProductsByOwnership from '../../data/products/use-products-by-ownership'; import getProductSlugsThatRequireUserConnection from '../../data/utils/get-product-slugs-that-require-user-connection'; import useAnalytics from '../use-analytics'; import useMyJetpackConnection from '../use-my-jetpack-connection'; @@ -25,6 +26,8 @@ const useSiteConnectionNotice = ( redBubbleAlerts: RedBubbleAlerts ) => { const redBubbleSlug = 'missing-connection'; const connectionError = redBubbleAlerts[ redBubbleSlug ]; + const { refetch: refetchOwnershipData } = useProductsByOwnership(); + useEffect( () => { if ( ! connectionError ) { return; @@ -45,6 +48,8 @@ const useSiteConnectionNotice = ( redBubbleAlerts: RedBubbleAlerts ) => { setNotice( NOTICE_SITE_CONNECTED, resetNotice ); delete redBubbleAlerts[ redBubbleSlug ]; window.myJetpackInitialState.redBubbleAlerts = redBubbleAlerts; + + refetchOwnershipData(); } ); }; @@ -125,6 +130,7 @@ const useSiteConnectionNotice = ( redBubbleAlerts: RedBubbleAlerts ) => { setNotice, siteIsRegistering, connectionError, + refetchOwnershipData, ] ); };