diff --git a/modules/ppcp-settings/resources/js/data/common/actions-thunk.js b/modules/ppcp-settings/resources/js/data/common/actions-thunk.js new file mode 100644 index 000000000..240f78f21 --- /dev/null +++ b/modules/ppcp-settings/resources/js/data/common/actions-thunk.js @@ -0,0 +1,171 @@ +import { select } from '@wordpress/data'; + +import ACTION_TYPES from './action-types'; +import { hydrate } from './actions'; +import { STORE_NAME } from './constants'; + +/** + * Side effect. Saves the persistent details to the WP database. + * + * @return {Action} The action. + */ +export const persist = function* () { + const data = yield select( STORE_NAME ).persistentData(); + + yield { type: ACTION_TYPES.DO_PERSIST_DATA, data }; +}; + +/** + * Side effect. Fetches the ISU-login URL for a sandbox account. + * + * @return {Action} The action. + */ +export const sandboxOnboardingUrl = function* () { + return yield { + type: ACTION_TYPES.DO_GENERATE_ONBOARDING_URL, + useSandbox: true, + products: [ 'EXPRESS_CHECKOUT' ], + }; +}; + +/** + * Side effect. Fetches the ISU-login URL for a production account. + * + * @param {string[]} products Which products/features to display in the ISU popup. + * @return {Action} The action. + */ +export const productionOnboardingUrl = function* ( products = [] ) { + return yield { + type: ACTION_TYPES.DO_GENERATE_ONBOARDING_URL, + useSandbox: false, + products, + }; +}; + +/** + * Side effect. Initiates a direct connection attempt using the provided client ID and secret. + * + * This action accepts parameters instead of fetching data from the Redux state because the + * values (ID and secret) are not managed by a central redux store, but might come from private + * component state. + * + * @param {string} clientId - AP client ID (always 80-characters, starting with "A"). + * @param {string} clientSecret - API client secret. + * @param {boolean} useSandbox - Whether the credentials are for a sandbox account. + * @return {Action} The action. + */ +export const authenticateWithCredentials = function* ( + clientId, + clientSecret, + useSandbox +) { + return yield { + type: ACTION_TYPES.DO_DIRECT_API_AUTHENTICATION, + clientId, + clientSecret, + useSandbox, + }; +}; + +/** + * Side effect. Completes the ISU login by authenticating the user via the one time sharedId and + * authCode provided by PayPal. + * + * This action accepts parameters instead of fetching data from the Redux state because all + * parameters are dynamically generated during the authentication process, and not managed by our + * Redux store. + * + * @param {string} sharedId - OAuth client ID; called "sharedId" to prevent confusion with the API client ID. + * @param {string} authCode - OAuth authorization code provided during onboarding. + * @param {boolean} useSandbox - Whether the credentials are for a sandbox account. + * @return {Action} The action. + */ +export const authenticateWithOAuth = function* ( + sharedId, + authCode, + useSandbox +) { + return yield { + type: ACTION_TYPES.DO_OAUTH_AUTHENTICATION, + sharedId, + authCode, + useSandbox, + }; +}; + +/** + * Side effect. Checks webhook simulation. + * + * @return {Action} The action. + */ +export const disconnectMerchant = function* () { + return yield { type: ACTION_TYPES.DO_DISCONNECT_MERCHANT }; +}; + +/** + * Side effect. Clears and refreshes the merchant data via a REST request. + * + * @return {Action} The action. + */ +export const refreshMerchantData = function* () { + const result = yield { type: ACTION_TYPES.DO_REFRESH_MERCHANT }; + + if ( result.success && result.merchant ) { + yield hydrate( result ); + } + + return result; +}; + +/** + * Side effect. + * Purges all feature status data via a REST request. + * Refreshes the merchant data via a REST request. + * + * @return {Action} The action. + */ +export const refreshFeatureStatuses = function* () { + const result = yield { type: ACTION_TYPES.DO_REFRESH_FEATURES }; + + if ( result && result.success ) { + // TODO: Review if we can get the updated feature details in the result.data instead of + // doing a second refreshMerchantData() request. + yield refreshMerchantData(); + } + + return result; +}; + +/** + * Side effect + * Refreshes subscribed webhooks via a REST request + * + * @return {Action} The action. + */ +export const resubscribeWebhooks = function* () { + const result = yield { type: ACTION_TYPES.DO_RESUBSCRIBE_WEBHOOKS }; + + if ( result && result.success ) { + yield hydrate( result ); + } + + return result; +}; + +/** + * Side effect. Starts webhook simulation. + * + * @return {Action} The action. + */ +export const startWebhookSimulation = function* () { + return yield { type: ACTION_TYPES.DO_START_WEBHOOK_SIMULATION }; +}; + +/** + * Side effect. Checks webhook simulation. + * + * @return {Action} The action. + */ +export const checkWebhookSimulationState = function* () { + return yield { type: ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION }; +}; diff --git a/modules/ppcp-settings/resources/js/data/common/actions.js b/modules/ppcp-settings/resources/js/data/common/actions.js index 58c9827a0..2e0573a9b 100644 --- a/modules/ppcp-settings/resources/js/data/common/actions.js +++ b/modules/ppcp-settings/resources/js/data/common/actions.js @@ -7,10 +7,7 @@ * @file */ -import { select } from '@wordpress/data'; - import ACTION_TYPES from './action-types'; -import { STORE_NAME } from './constants'; /** * @typedef {Object} Action An action object that is handled by a reducer or control. @@ -86,6 +83,35 @@ export const setActiveModal = ( activeModal ) => export const setActiveHighlight = ( activeHighlight ) => setTransient( 'activeHighlight', activeHighlight ); +/** + * Persistent. Sets the sandbox mode on or off. + * + * @param {boolean} useSandbox + * @return {Action} The action. + */ +export const setSandboxMode = ( useSandbox ) => + setPersistent( 'useSandbox', useSandbox ); + +/** + * Persistent. Toggles the "Manual Connection" mode on or off. + * + * @param {boolean} useManualConnection + * @return {Action} The action. + */ +export const setManualConnectionMode = ( useManualConnection ) => + setPersistent( 'useManualConnection', useManualConnection ); + +/** + * Persistent. Changes the "webhooks" value. + * + * @param {string} webhooks + * @return {Action} The action. + */ +export const setWebhooks = ( webhooks ) => + setPersistent( 'webhooks', webhooks ); + +// Activity control - see useBusyState() hook. + /** * Transient (Activity): Marks the start of an async activity * Think of it as "setIsBusy(true)" @@ -117,198 +143,3 @@ export const stopActivity = ( id ) => ( { type: ACTION_TYPES.STOP_ACTIVITY, payload: { id }, } ); - -/** - * Persistent. Sets the sandbox mode on or off. - * - * @param {boolean} useSandbox - * @return {Action} The action. - */ -export const setSandboxMode = ( useSandbox ) => - setPersistent( 'useSandbox', useSandbox ); - -/** - * Persistent. Toggles the "Manual Connection" mode on or off. - * - * @param {boolean} useManualConnection - * @return {Action} The action. - */ -export const setManualConnectionMode = ( useManualConnection ) => - setPersistent( 'useManualConnection', useManualConnection ); - -/** - * Side effect. Saves the persistent details to the WP database. - * - * @return {Action} The action. - */ -export const persist = function* () { - const data = yield select( STORE_NAME ).persistentData(); - - yield { type: ACTION_TYPES.DO_PERSIST_DATA, data }; -}; - -/** - * Side effect. Fetches the ISU-login URL for a sandbox account. - * - * @return {Action} The action. - */ -export const sandboxOnboardingUrl = function* () { - return yield { - type: ACTION_TYPES.DO_GENERATE_ONBOARDING_URL, - useSandbox: true, - products: [ 'EXPRESS_CHECKOUT' ], - }; -}; - -/** - * Side effect. Fetches the ISU-login URL for a production account. - * - * @param {string[]} products Which products/features to display in the ISU popup. - * @return {Action} The action. - */ -export const productionOnboardingUrl = function* ( products = [] ) { - return yield { - type: ACTION_TYPES.DO_GENERATE_ONBOARDING_URL, - useSandbox: false, - products, - }; -}; - -/** - * Side effect. Initiates a direct connection attempt using the provided client ID and secret. - * - * This action accepts parameters instead of fetching data from the Redux state because the - * values (ID and secret) are not managed by a central redux store, but might come from private - * component state. - * - * @param {string} clientId - AP client ID (always 80-characters, starting with "A"). - * @param {string} clientSecret - API client secret. - * @param {boolean} useSandbox - Whether the credentials are for a sandbox account. - * @return {Action} The action. - */ -export const authenticateWithCredentials = function* ( - clientId, - clientSecret, - useSandbox -) { - return yield { - type: ACTION_TYPES.DO_DIRECT_API_AUTHENTICATION, - clientId, - clientSecret, - useSandbox, - }; -}; - -/** - * Side effect. Completes the ISU login by authenticating the user via the one time sharedId and - * authCode provided by PayPal. - * - * This action accepts parameters instead of fetching data from the Redux state because all - * parameters are dynamically generated during the authentication process, and not managed by our - * Redux store. - * - * @param {string} sharedId - OAuth client ID; called "sharedId" to prevent confusion with the API client ID. - * @param {string} authCode - OAuth authorization code provided during onboarding. - * @param {boolean} useSandbox - Whether the credentials are for a sandbox account. - * @return {Action} The action. - */ -export const authenticateWithOAuth = function* ( - sharedId, - authCode, - useSandbox -) { - return yield { - type: ACTION_TYPES.DO_OAUTH_AUTHENTICATION, - sharedId, - authCode, - useSandbox, - }; -}; - -/** - * Side effect. Checks webhook simulation. - * - * @return {Action} The action. - */ -export const disconnectMerchant = function* () { - return yield { type: ACTION_TYPES.DO_DISCONNECT_MERCHANT }; -}; - -/** - * Side effect. Clears and refreshes the merchant data via a REST request. - * - * @return {Action} The action. - */ -export const refreshMerchantData = function* () { - const result = yield { type: ACTION_TYPES.DO_REFRESH_MERCHANT }; - - if ( result.success && result.merchant ) { - yield hydrate( result ); - } - - return result; -}; - -/** - * Side effect. - * Purges all feature status data via a REST request. - * Refreshes the merchant data via a REST request. - * - * @return {Action} The action. - */ -export const refreshFeatureStatuses = function* () { - const result = yield { type: ACTION_TYPES.DO_REFRESH_FEATURES }; - - if ( result && result.success ) { - // TODO: Review if we can get the updated feature details in the result.data instead of - // doing a second refreshMerchantData() request. - yield refreshMerchantData(); - } - - return result; -}; - -/** - * Persistent. Changes the "webhooks" value. - * - * @param {string} webhooks - * @return {Action} The action. - */ -export const setWebhooks = ( webhooks ) => ( { - type: ACTION_TYPES.SET_PERSISTENT, - payload: { webhooks }, -} ); - -/** - * Side effect - * Refreshes subscribed webhooks via a REST request - * - * @return {Action} The action. - */ -export const resubscribeWebhooks = function* () { - const result = yield { type: ACTION_TYPES.DO_RESUBSCRIBE_WEBHOOKS }; - - if ( result && result.success ) { - yield hydrate( result ); - } - - return result; -}; - -/** - * Side effect. Starts webhook simulation. - * - * @return {Action} The action. - */ -export const startWebhookSimulation = function* () { - return yield { type: ACTION_TYPES.DO_START_WEBHOOK_SIMULATION }; -}; - -/** - * Side effect. Checks webhook simulation. - * - * @return {Action} The action. - */ -export const checkWebhookSimulationState = function* () { - return yield { type: ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION }; -}; diff --git a/modules/ppcp-settings/resources/js/data/common/index.js b/modules/ppcp-settings/resources/js/data/common/index.js index 3bd6e4459..9e4f22782 100644 --- a/modules/ppcp-settings/resources/js/data/common/index.js +++ b/modules/ppcp-settings/resources/js/data/common/index.js @@ -5,6 +5,7 @@ import { STORE_NAME } from './constants'; import reducer from './reducer'; import * as selectors from './selectors'; import * as actions from './actions'; +import * as thunkActions from './actions-thunk'; import * as hooks from './hooks'; import { resolvers } from './resolvers'; import { controls } from './controls'; @@ -19,7 +20,7 @@ export const initStore = () => { const store = createReduxStore( STORE_NAME, { reducer, controls: { ...wpControls, ...controls }, - actions, + actions: { ...actions, ...thunkActions }, selectors, resolvers, } );