diff --git a/plugins/woocommerce-admin/client/task-list/tasks/Marketing/index.tsx b/plugins/woocommerce-admin/client/task-list/tasks/Marketing/index.tsx index 1ee7897cc8b..9f84cb49cbf 100644 --- a/plugins/woocommerce-admin/client/task-list/tasks/Marketing/index.tsx +++ b/plugins/woocommerce-admin/client/task-list/tasks/Marketing/index.tsx @@ -2,12 +2,15 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import apiFetch from '@wordpress/api-fetch'; import { Card, CardHeader, Spinner } from '@wordpress/components'; -import { PLUGINS_STORE_NAME, WCDataSelector } from '@woocommerce/data'; +import { + ONBOARDING_STORE_NAME, + PLUGINS_STORE_NAME, + WCDataSelector, +} from '@woocommerce/data'; import { recordEvent } from '@woocommerce/tracks'; import { Text } from '@woocommerce/experimental'; -import { useEffect, useMemo, useState } from '@wordpress/element'; +import { useMemo, useState } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; /** @@ -18,44 +21,33 @@ import { createNoticesFromResponse } from '~/lib/notices'; import { PluginList, PluginListProps } from './PluginList'; import { PluginProps } from './Plugin'; -type ExtensionList = { - key: string; - title: string; - plugins: Extension[]; -}; - -type Extension = { - description: string; - key: string; - image_url: string; - manage_url: string; - name: string; - slug: string; -}; - const ALLOWED_PLUGIN_LISTS = [ 'reach', 'grow' ]; export const Marketing: React.FC = () => { - const [ fetchedExtensions, setFetchedExtensions ] = useState< - ExtensionList[] - >( [] ); const [ currentPlugin, setCurrentPlugin ] = useState< string | null >( null ); - const [ isFetching, setIsFetching ] = useState( true ); const { installAndActivatePlugins } = useDispatch( PLUGINS_STORE_NAME ); - const { activePlugins, installedPlugins } = useSelect( - ( select: WCDataSelector ) => { - const { getActivePlugins, getInstalledPlugins } = select( - PLUGINS_STORE_NAME - ); + const { + activePlugins, + freeExtensions, + installedPlugins, + isResolving, + } = useSelect( ( select: WCDataSelector ) => { + const { getActivePlugins, getInstalledPlugins } = select( + PLUGINS_STORE_NAME + ); + const { getFreeExtensions, hasFinishedResolution } = select( + ONBOARDING_STORE_NAME + ); - return { - activePlugins: getActivePlugins(), - installedPlugins: getInstalledPlugins(), - }; - } - ); + return { + activePlugins: getActivePlugins(), + freeExtensions: getFreeExtensions(), + installedPlugins: getInstalledPlugins(), + isResolving: ! hasFinishedResolution( 'getFreeExtensions' ), + }; + } ); const transformExtensionToPlugin = ( extension: Extension @@ -73,26 +65,10 @@ export const Marketing: React.FC = () => { }; }; - useEffect( () => { - apiFetch( { - path: '/wc-admin/onboarding/free-extensions', - } ) - .then( ( results: ExtensionList[] ) => { - if ( results?.length ) { - setFetchedExtensions( results ); - } - setIsFetching( false ); - } ) - .catch( () => { - // @todo Handle error checking. - setIsFetching( false ); - } ); - }, [] ); - const [ installedExtensions, pluginLists ] = useMemo( () => { const installed: PluginProps[] = []; const lists: PluginListProps[] = []; - fetchedExtensions.forEach( ( list ) => { + freeExtensions.forEach( ( list ) => { if ( ! ALLOWED_PLUGIN_LISTS.includes( list.key ) ) { return; } @@ -119,7 +95,7 @@ export const Marketing: React.FC = () => { } ); return [ installed, lists ]; - }, [ installedPlugins, activePlugins, fetchedExtensions ] ); + }, [ installedPlugins, activePlugins, freeExtensions ] ); const installAndActivate = ( slug: string ) => { setCurrentPlugin( slug ); @@ -140,7 +116,7 @@ export const Marketing: React.FC = () => { } ); }; - if ( isFetching ) { + if ( isResolving ) { return ; } diff --git a/plugins/woocommerce-admin/packages/data/src/onboarding/action-types.js b/plugins/woocommerce-admin/packages/data/src/onboarding/action-types.js index 2e6c64e2f1f..0cf7ef689c7 100644 --- a/plugins/woocommerce-admin/packages/data/src/onboarding/action-types.js +++ b/plugins/woocommerce-admin/packages/data/src/onboarding/action-types.js @@ -4,6 +4,8 @@ const TYPES = { SET_PROFILE_ITEMS: 'SET_PROFILE_ITEMS', SET_TASKS_STATUS: 'SET_TASKS_STATUS', GET_PAYMENT_METHODS_SUCCESS: 'GET_PAYMENT_METHODS_SUCCESS', + GET_FREE_EXTENSIONS_ERROR: 'GET_FREE_EXTENSIONS_ERROR', + GET_FREE_EXTENSIONS_SUCCESS: 'GET_FREE_EXTENSIONS_SUCCESS', }; export default TYPES; diff --git a/plugins/woocommerce-admin/packages/data/src/onboarding/actions.js b/plugins/woocommerce-admin/packages/data/src/onboarding/actions.js index f1c4539225e..e1b95b291f0 100644 --- a/plugins/woocommerce-admin/packages/data/src/onboarding/actions.js +++ b/plugins/woocommerce-admin/packages/data/src/onboarding/actions.js @@ -9,6 +9,20 @@ import { apiFetch } from '@wordpress/data-controls'; import TYPES from './action-types'; import { WC_ADMIN_NAMESPACE } from '../constants'; +export function getFreeExtensionsError( error ) { + return { + type: TYPES.GET_FREE_EXTENSIONS_ERROR, + error, + }; +} + +export function getFreeExtensionsSuccess( freeExtensions ) { + return { + type: TYPES.GET_FREE_EXTENSIONS_SUCCESS, + freeExtensions, + }; +} + export function setError( selector, error ) { return { type: TYPES.SET_ERROR, diff --git a/plugins/woocommerce-admin/packages/data/src/onboarding/reducer.js b/plugins/woocommerce-admin/packages/data/src/onboarding/reducer.js index 63a0e4d02a7..cffb16c810c 100644 --- a/plugins/woocommerce-admin/packages/data/src/onboarding/reducer.js +++ b/plugins/woocommerce-admin/packages/data/src/onboarding/reducer.js @@ -5,6 +5,7 @@ import TYPES from './action-types'; export const defaultState = { errors: {}, + freeExtensions: [], profileItems: { business_extensions: null, completed: null, @@ -28,6 +29,7 @@ export const defaultState = { const onboarding = ( state = defaultState, { + freeExtensions, type, profileItems, paymentMethods, @@ -72,6 +74,19 @@ const onboarding = ( ...state, paymentMethods, }; + case TYPES.GET_FREE_EXTENSIONS_ERROR: + return { + ...state, + errors: { + ...state.errors, + getFreeExtensions: error, + }, + }; + case TYPES.GET_FREE_EXTENSIONS_SUCCESS: + return { + ...state, + freeExtensions, + }; default: return state; } diff --git a/plugins/woocommerce-admin/packages/data/src/onboarding/resolvers.js b/plugins/woocommerce-admin/packages/data/src/onboarding/resolvers.js index 3e65128e315..bc2e702a2cd 100644 --- a/plugins/woocommerce-admin/packages/data/src/onboarding/resolvers.js +++ b/plugins/woocommerce-admin/packages/data/src/onboarding/resolvers.js @@ -8,6 +8,8 @@ import { apiFetch } from '@wordpress/data-controls'; */ import { WC_ADMIN_NAMESPACE } from '../constants'; import { + getFreeExtensionsError, + getFreeExtensionsSuccess, setProfileItems, setError, setTasksStatus, @@ -52,3 +54,16 @@ export function* getPaymentGatewaySuggestions() { yield setError( 'getPaymentGatewaySuggestions', error ); } } + +export function* getFreeExtensions() { + try { + const results = yield apiFetch( { + path: WC_ADMIN_NAMESPACE + '/onboarding/free-extensions', + method: 'GET', + } ); + + yield getFreeExtensionsSuccess( results ); + } catch ( error ) { + yield getFreeExtensionsError( error ); + } +} diff --git a/plugins/woocommerce-admin/packages/data/src/onboarding/selectors.ts b/plugins/woocommerce-admin/packages/data/src/onboarding/selectors.ts index 6f9cc322872..4183a258e69 100644 --- a/plugins/woocommerce-admin/packages/data/src/onboarding/selectors.ts +++ b/plugins/woocommerce-admin/packages/data/src/onboarding/selectors.ts @@ -3,6 +3,12 @@ */ import { WPDataSelectors, RuleProcessor } from '../types'; +export const getFreeExtensions = ( + state: OnboardingState +): ExtensionList[] => { + return state.freeExtensions || []; +}; + export const getProfileItems = ( state: OnboardingState ): ProfileItemsState | Record< string, never > => { @@ -47,6 +53,7 @@ export type OnboardingSelectors = { } & WPDataSelectors; export type OnboardingState = { + freeExtensions: ExtensionList[]; profileItems: ProfileItemsState; tasksStatus: TasksStatusState; paymentMethods: PaymentMethodsState[]; @@ -150,3 +157,18 @@ export type PaymentMethodsState = { api_details_url: string; manage_url: string; }; + +export type ExtensionList = { + key: string; + title: string; + plugins: Extension[]; +}; + +export type Extension = { + description: string; + key: string; + image_url: string; + manage_url: string; + name: string; + slug: string; +};