From 7ae4184d302ab76a840a9f53f03f8a66aaf1f121 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Wed, 20 Nov 2024 17:21:09 +0100
Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Apply=20new=20code=20style?=
=?UTF-8?q?=20to=20=E2=80=9Ccommon=E2=80=9D=20store?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/common/action-types.js | 4 +-
.../resources/js/data/common/actions.js | 100 ++++++++++--------
.../resources/js/data/common/constants.js | 6 +-
.../resources/js/data/common/controls.js | 19 ++--
.../resources/js/data/common/hooks.js | 17 ++-
.../resources/js/data/common/index.js | 24 ++++-
.../resources/js/data/common/reducer.js | 5 +-
.../resources/js/data/common/resolvers.js | 43 ++++----
.../resources/js/data/common/selectors.js | 21 +---
9 files changed, 130 insertions(+), 109 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/common/action-types.js b/modules/ppcp-settings/resources/js/data/common/action-types.js
index 1645547d9..5d5968591 100644
--- a/modules/ppcp-settings/resources/js/data/common/action-types.js
+++ b/modules/ppcp-settings/resources/js/data/common/action-types.js
@@ -1,9 +1,6 @@
/**
* Action Types: Define unique identifiers for actions across all store modules.
*
- * Keys are module-internal and can have any value.
- * Values must be unique across all store modules to avoid collisions.
- *
* @file
*/
@@ -13,6 +10,7 @@ export default {
// Persistent data.
SET_PERSISTENT: 'COMMON:SET_PERSISTENT',
+ HYDRATE: 'COMMON:HYDRATE',
// Controls - always start with "DO_".
DO_PERSIST_DATA: 'COMMON:DO_PERSIST_DATA',
diff --git a/modules/ppcp-settings/resources/js/data/common/actions.js b/modules/ppcp-settings/resources/js/data/common/actions.js
index 3992e0ff5..4586b8923 100644
--- a/modules/ppcp-settings/resources/js/data/common/actions.js
+++ b/modules/ppcp-settings/resources/js/data/common/actions.js
@@ -2,7 +2,6 @@
* Action Creators: Define functions to create action objects.
*
* These functions update state or trigger side effects (e.g., async operations).
- * Exported functions must have unique names across all store modules.
* Actions are categorized as Transient, Persistent, or Side effect.
*
* @file
@@ -10,91 +9,98 @@
import ACTION_TYPES from './action-types';
+/**
+ * @typedef {Object} Action An action object that is handled by a reducer or control.
+ * @property {string} type - The action type.
+ * @property {Object?} payload - Optional payload for the action.
+ */
+
/**
* Transient. Marks the onboarding details as "ready", i.e., fully initialized.
*
* @param {boolean} isReady
- * @return {{type: string, isReady: boolean}} The action.
+ * @return {Action} The action.
*/
-export const setIsReady = ( isReady ) => {
- return {
- type: ACTION_TYPES.SET_TRANSIENT,
- isReady,
- };
-};
+export const setIsReady = ( isReady ) => ( {
+ type: ACTION_TYPES.SET_TRANSIENT,
+ payload: { isReady },
+} );
/**
* Transient. Changes the "saving" flag.
*
* @param {boolean} isSaving
- * @return {{type: string, isSaving: boolean}} The action.
+ * @return {Action} The action.
*/
-export const setIsSaving = ( isSaving ) => {
- return {
- type: ACTION_TYPES.SET_TRANSIENT,
- isSaving,
- };
-};
+export const setIsSaving = ( isSaving ) => ( {
+ type: ACTION_TYPES.SET_TRANSIENT,
+ payload: { isSaving },
+} );
+
+/**
+ * Transient. Changes the "manual connection is busy" flag.
+ *
+ * @param {boolean} isBusy
+ * @return {Action} The action.
+ */
+export const setIsBusy = ( isBusy ) => ( {
+ type: ACTION_TYPES.SET_TRANSIENT,
+ payload: { isBusy },
+} );
/**
* Persistent. Sets the sandbox mode on or off.
*
* @param {boolean} useSandbox
- * @return {{type: string, useSandbox: boolean}} An action.
+ * @return {Action} The action.
*/
-export const setSandboxMode = ( useSandbox ) => {
- return {
- type: ACTION_TYPES.SET_PERSISTENT,
- useSandbox,
- };
-};
+export const setSandboxMode = ( useSandbox ) => ( {
+ type: ACTION_TYPES.SET_PERSISTENT,
+ payload: { useSandbox },
+} );
/**
* Persistent. Toggles the "Manual Connection" mode on or off.
*
* @param {boolean} useManualConnection
- * @return {{type: string, useManualConnection: boolean}} An action.
+ * @return {Action} The action.
*/
-export const setManualConnectionMode = ( useManualConnection ) => {
- return {
- type: ACTION_TYPES.SET_PERSISTENT,
- useManualConnection,
- };
-};
+export const setManualConnectionMode = ( useManualConnection ) => ( {
+ type: ACTION_TYPES.SET_PERSISTENT,
+ payload: { useManualConnection },
+} );
/**
* Persistent. Changes the "client ID" value.
*
* @param {string} clientId
- * @return {{type: string, clientId: string}} The action.
+ * @return {Action} The action.
*/
-export const setClientId = ( clientId ) => {
- return {
- type: ACTION_TYPES.SET_PERSISTENT,
- clientId,
- };
-};
+export const setClientId = ( clientId ) => ( {
+ type: ACTION_TYPES.SET_PERSISTENT,
+ payload: { clientId },
+} );
/**
* Persistent. Changes the "client secret" value.
*
* @param {string} clientSecret
- * @return {{type: string, clientSecret: string}} The action.
+ * @return {Action} The action.
*/
-export const setClientSecret = ( clientSecret ) => {
- return {
- type: ACTION_TYPES.SET_PERSISTENT,
- clientSecret,
- };
-};
+export const setClientSecret = ( clientSecret ) => ( {
+ type: ACTION_TYPES.SET_PERSISTENT,
+ payload: { clientSecret },
+} );
/**
* Side effect. Saves the persistent details to the WP database.
*
- * @return {{type: string}} The action.
+ * @return {Action} The action.
*/
-export function* commonPersist() {
- return {
+export const persist = function* () {
+ yield setIsBusy( true );
+ yield {
type: ACTION_TYPES.DO_PERSIST_DATA,
};
-}
+ yield setIsBusy( false );
+};
diff --git a/modules/ppcp-settings/resources/js/data/common/constants.js b/modules/ppcp-settings/resources/js/data/common/constants.js
index 365bfe305..881cac2f5 100644
--- a/modules/ppcp-settings/resources/js/data/common/constants.js
+++ b/modules/ppcp-settings/resources/js/data/common/constants.js
@@ -5,7 +5,7 @@
*
* @type {string}
*/
-export const STORE_KEY = 'common';
+export const STORE_NAME = 'wc/paypal/common';
/**
* REST path to hydrate data of this module by loading data from the WP DB..
@@ -14,7 +14,7 @@ export const STORE_KEY = 'common';
*
* @type {string}
*/
-export const REST_HYDRATE_PATH = 'common';
+export const REST_HYDRATE_PATH = '/wc/v3/wc_paypal/common';
/**
* REST path to persist data of this module to the WP DB.
@@ -23,4 +23,4 @@ export const REST_HYDRATE_PATH = 'common';
*
* @type {string}
*/
-export const REST_PERSIST_PATH = 'common';
+export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/common';
diff --git a/modules/ppcp-settings/resources/js/data/common/controls.js b/modules/ppcp-settings/resources/js/data/common/controls.js
index 45b3e6ea5..e18bb48ec 100644
--- a/modules/ppcp-settings/resources/js/data/common/controls.js
+++ b/modules/ppcp-settings/resources/js/data/common/controls.js
@@ -1,32 +1,27 @@
/**
* Controls: Implement side effects, typically asynchronous operations.
*
- * Controls use ACTION_TYPES keys as identifiers to ensure uniqueness.
+ * Controls use ACTION_TYPES keys as identifiers.
* They are triggered by corresponding actions and handle external interactions.
*
* @file
*/
-import { select } from '@wordpress/data';
-import { apiFetch } from '@wordpress/api-fetch';
+import apiFetch from '@wordpress/api-fetch';
-import { NAMESPACE, STORE_NAME } from '../constants';
import { REST_PERSIST_PATH } from './constants';
import ACTION_TYPES from './action-types';
-export const controls = {
- [ ACTION_TYPES.DO_PERSIST_DATA ]: async () => {
- const path = `${ NAMESPACE }/${ REST_PERSIST_PATH }`;
- const data = select( STORE_NAME ).getPersistentData();
+export const controls = {
+ async [ ACTION_TYPES.DO_PERSIST_DATA ]( { data } ) {
try {
return await apiFetch( {
- path,
- method: 'post',
+ path: REST_PERSIST_PATH,
+ method: 'POST',
data,
} );
} catch ( error ) {
- console.error( 'Error saving progress.', error );
- throw error;
+ console.error( 'Error saving data.', error );
}
},
};
diff --git a/modules/ppcp-settings/resources/js/data/common/hooks.js b/modules/ppcp-settings/resources/js/data/common/hooks.js
index a201c6d37..907ee00f3 100644
--- a/modules/ppcp-settings/resources/js/data/common/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/common/hooks.js
@@ -3,7 +3,22 @@
*
* These encapsulate store interactions, offering a consistent interface.
* Hooks simplify data access and manipulation for components.
- * Exported hooks must have unique names across all store modules.
*
* @file
*/
+
+import { useSelect } from '@wordpress/data';
+
+import { STORE_NAME } from './constants';
+
+const useTransient = ( key ) =>
+ useSelect(
+ ( select ) => select( STORE_NAME ).transientData()?.[ key ],
+ [ key ]
+ );
+
+const usePersistent = ( key ) =>
+ useSelect(
+ ( select ) => select( STORE_NAME ).persistentData()?.[ key ],
+ [ key ]
+ );
diff --git a/modules/ppcp-settings/resources/js/data/common/index.js b/modules/ppcp-settings/resources/js/data/common/index.js
index a8c685d37..60f81da60 100644
--- a/modules/ppcp-settings/resources/js/data/common/index.js
+++ b/modules/ppcp-settings/resources/js/data/common/index.js
@@ -1,8 +1,26 @@
-import { STORE_KEY } from './constants';
+import { createReduxStore, register } from '@wordpress/data';
+import { controls as wpControls } from '@wordpress/data-controls';
+
+import { STORE_NAME } from './constants';
import reducer from './reducer';
import * as selectors from './selectors';
import * as actions from './actions';
-import * as resolvers from './resolvers';
+import * as hooks from './hooks';
+import { resolvers } from './resolvers';
import { controls } from './controls';
-export { reducer, selectors, actions, resolvers, controls, STORE_KEY };
+export const initStore = () => {
+ const store = createReduxStore( STORE_NAME, {
+ reducer,
+ controls: { ...wpControls, ...controls },
+ actions,
+ selectors,
+ resolvers,
+ } );
+
+ register( store );
+};
+
+export { hooks };
+
+export { STORE_NAME };
diff --git a/modules/ppcp-settings/resources/js/data/common/reducer.js b/modules/ppcp-settings/resources/js/data/common/reducer.js
index 583fd7540..d16106379 100644
--- a/modules/ppcp-settings/resources/js/data/common/reducer.js
+++ b/modules/ppcp-settings/resources/js/data/common/reducer.js
@@ -2,7 +2,6 @@
* Reducer: Defines store structure and state updates for this module.
*
* Manages both transient (temporary) and persistent (saved) state.
- * Each module uses isolated memory objects to prevent conflicts.
* The initial state must define all properties, as dynamic additions are not supported.
*
* @file
@@ -16,6 +15,7 @@ import ACTION_TYPES from './action-types';
const defaultTransient = {
isReady: false,
isSaving: false,
+ isBusy: false,
};
const defaultPersistent = {
@@ -38,6 +38,9 @@ const commonReducer = createReducer( defaultTransient, defaultPersistent, {
[ ACTION_TYPES.SET_PERSISTENT ]: ( state, action ) =>
setPersistent( state, action ),
+
+ [ ACTION_TYPES.HYDRATE ]: ( state, payload ) =>
+ setPersistent( state, payload.data ),
} );
export default commonReducer;
diff --git a/modules/ppcp-settings/resources/js/data/common/resolvers.js b/modules/ppcp-settings/resources/js/data/common/resolvers.js
index 2358496be..ceebca53f 100644
--- a/modules/ppcp-settings/resources/js/data/common/resolvers.js
+++ b/modules/ppcp-settings/resources/js/data/common/resolvers.js
@@ -2,7 +2,7 @@
* Resolvers: Handle asynchronous data fetching for the store.
*
* These functions update store state with data from external sources.
- * Each resolver corresponds to a specific selector but must have a unique name.
+ * Each resolver corresponds to a specific selector (selector with same name must exist).
* Resolvers are called automatically when selectors request unavailable data.
*
* @file
@@ -12,26 +12,25 @@ import { dispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { apiFetch } from '@wordpress/data-controls';
-import { NAMESPACE } from '../constants';
-import { setIsReady, setCommonDetails } from './actions';
-import { REST_HYDRATE_PATH } from './constants';
+import { STORE_NAME, REST_HYDRATE_PATH } from './constants';
-/**
- * Retrieve settings from the site's REST API.
- */
-export function* commonPersistentData() {
- const path = `${ NAMESPACE }/${ REST_HYDRATE_PATH }`;
+export const resolvers = {
+ /**
+ * Retrieve settings from the site's REST API.
+ */
+ *persistentData() {
+ try {
+ const result = yield apiFetch( { path: REST_HYDRATE_PATH } );
- try {
- const result = yield apiFetch( { path } );
- yield setCommonDetails( result );
- yield setIsReady( true );
- } catch ( e ) {
- yield dispatch( 'core/notices' ).createErrorNotice(
- __(
- 'Error retrieving plugin details.',
- 'woocommerce-paypal-payments'
- )
- );
- }
-}
+ yield dispatch( STORE_NAME ).hydrate( result );
+ yield dispatch( STORE_NAME ).setIsReady( true );
+ } catch ( e ) {
+ yield dispatch( 'core/notices' ).createErrorNotice(
+ __(
+ 'Error retrieving plugin details.',
+ 'woocommerce-paypal-payments'
+ )
+ );
+ }
+ },
+};
diff --git a/modules/ppcp-settings/resources/js/data/common/selectors.js b/modules/ppcp-settings/resources/js/data/common/selectors.js
index 4ea6e86a7..14334fcf3 100644
--- a/modules/ppcp-settings/resources/js/data/common/selectors.js
+++ b/modules/ppcp-settings/resources/js/data/common/selectors.js
@@ -3,32 +3,19 @@
*
* These functions provide a consistent interface for accessing store data.
* They allow components to retrieve data without knowing the store structure.
- * Exported functions must have unique names across all store modules.
*
* @file
*/
-import { STORE_KEY } from './constants';
-
const EMPTY_OBJ = Object.freeze( {} );
-const getState = ( state ) => {
- if ( ! state ) {
- return EMPTY_OBJ;
- }
+const getState = ( state ) => state || EMPTY_OBJ;
- return state[ STORE_KEY ] || EMPTY_OBJ;
-};
-
-export const commonPersistentData = ( state ) => {
+export const persistentData = ( state ) => {
return getState( state ).data || EMPTY_OBJ;
};
-export const commonTransientData = ( state ) => {
- const { data, flags, ...transientState } = getState( state );
+export const transientData = ( state ) => {
+ const { data, ...transientState } = getState( state );
return transientState || EMPTY_OBJ;
};
-
-export const commonFlags = ( state ) => {
- return getState( state ).flags || EMPTY_OBJ;
-};