From 5afdc815efdf148cad0fc77454e4dd8091279c88 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Fri, 14 Feb 2025 16:19:44 +0100
Subject: [PATCH 01/23] =?UTF-8?q?=F0=9F=90=9B=20Enable=20the=20PayPal=20me?=
=?UTF-8?q?thod=20after=20onboarding?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This gateway should be active for every merchant right after onboarding, regardless of seller-type of onboarding choices.
---
modules/ppcp-settings/src/Service/SettingsDataManager.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-settings/src/Service/SettingsDataManager.php b/modules/ppcp-settings/src/Service/SettingsDataManager.php
index 2feefc4ee..4af72b7bd 100644
--- a/modules/ppcp-settings/src/Service/SettingsDataManager.php
+++ b/modules/ppcp-settings/src/Service/SettingsDataManager.php
@@ -211,7 +211,8 @@ class SettingsDataManager {
$this->payment_methods->toggle_method_state( $method['id'], false );
}
- // Always enable Venmo and Pay Later.
+ // Always enable PayPal, Venmo and Pay Later.
+ $this->payment_methods->toggle_method_state( PayPalGateway::ID, true );
$this->payment_methods->toggle_method_state( 'venmo', true );
$this->payment_methods->toggle_method_state( 'pay-later', true );
From 838fd6a1a041ad6f958a3ce152324f0515c5fce5 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Fri, 14 Feb 2025 17:45:05 +0100
Subject: [PATCH 02/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Apply=20new=20hook-p?=
=?UTF-8?q?attern=20to=20payment=20store?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/payment/hooks.js | 54 +++++++++++++------
1 file changed, 37 insertions(+), 17 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/payment/hooks.js b/modules/ppcp-settings/resources/js/data/payment/hooks.js
index 253710580..7cbd81382 100644
--- a/modules/ppcp-settings/resources/js/data/payment/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/payment/hooks.js
@@ -7,21 +7,38 @@
* @file
*/
-import { useDispatch } from '@wordpress/data';
+import { useDispatch, useSelect } from '@wordpress/data';
import { STORE_NAME } from './constants';
import { createHooksForStore } from '../utils';
+import { useMemo } from '@wordpress/element';
+
+/**
+ * Single source of truth for access Redux details.
+ *
+ * This hook returns a stable API to access actions, selectors and special hooks to generate
+ * getter- and setters for transient or persistent properties.
+ *
+ * @return {{select, dispatch, useTransient, usePersistent}} Store data API.
+ */
+const useStoreData = () => {
+ const select = useSelect( ( selectors ) => selectors( STORE_NAME ), [] );
+ const dispatch = useDispatch( STORE_NAME );
+ const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
+
+ return useMemo(
+ () => ( {
+ select,
+ dispatch,
+ useTransient,
+ usePersistent,
+ } ),
+ [ select, dispatch, useTransient, usePersistent ]
+ );
+};
const useHooks = () => {
- const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
- const { persist, setPersistent, changePaymentSettings } =
- useDispatch( STORE_NAME );
-
- // Read-only flags and derived state.
- // Nothing here yet.
-
- // Transient accessors.
- const [ isReady ] = useTransient( 'isReady' );
+ const { usePersistent } = useStoreData();
// PayPal checkout.
const [ paypal ] = usePersistent( 'ppcp-gateway' );
@@ -58,10 +75,6 @@ const useHooks = () => {
);
return {
- persist,
- isReady,
- setPersistent,
- changePaymentSettings,
paypal,
venmo,
payLater,
@@ -88,9 +101,16 @@ const useHooks = () => {
};
export const useStore = () => {
- const { persist, isReady, setPersistent, changePaymentSettings } =
- useHooks();
- return { persist, isReady, setPersistent, changePaymentSettings };
+ const { useTransient, dispatch } = useStoreData();
+ const { persist, setPersistent, changePaymentSettings } = dispatch;
+ const [ isReady ] = useTransient( 'isReady' );
+
+ return {
+ persist,
+ setPersistent,
+ changePaymentSettings,
+ isReady,
+ };
};
export const usePaymentMethods = () => {
From 3f5f587e888abd68469f995c98774e5c5c5aa6d1 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Fri, 14 Feb 2025 17:45:31 +0100
Subject: [PATCH 03/23] =?UTF-8?q?=E2=9C=A8=20First=20store-refresh=20actio?=
=?UTF-8?q?n=20in=20payment=20store?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/payment/actions.js | 13 +++++++++++++
.../resources/js/data/payment/hooks.js | 3 ++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-settings/resources/js/data/payment/actions.js b/modules/ppcp-settings/resources/js/data/payment/actions.js
index 1107d5bfb..d8398795a 100644
--- a/modules/ppcp-settings/resources/js/data/payment/actions.js
+++ b/modules/ppcp-settings/resources/js/data/payment/actions.js
@@ -94,3 +94,16 @@ export function persist() {
} );
};
}
+
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStoreSelector( 'persistentData' );
+
+ select.persistentData();
+ };
+}
diff --git a/modules/ppcp-settings/resources/js/data/payment/hooks.js b/modules/ppcp-settings/resources/js/data/payment/hooks.js
index 7cbd81382..5a330f1b2 100644
--- a/modules/ppcp-settings/resources/js/data/payment/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/payment/hooks.js
@@ -102,11 +102,12 @@ const useHooks = () => {
export const useStore = () => {
const { useTransient, dispatch } = useStoreData();
- const { persist, setPersistent, changePaymentSettings } = dispatch;
+ const { persist, refresh, setPersistent, changePaymentSettings } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
return {
persist,
+ refresh,
setPersistent,
changePaymentSettings,
isReady,
From 10527e507ace36f57e36baea94846efd5fee8ab4 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Fri, 14 Feb 2025 17:45:45 +0100
Subject: [PATCH 04/23] =?UTF-8?q?=F0=9F=8E=A8=20Comments=20and=20white=20s?=
=?UTF-8?q?pace?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modules/ppcp-settings/resources/js/data/payment/reducer.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/modules/ppcp-settings/resources/js/data/payment/reducer.js b/modules/ppcp-settings/resources/js/data/payment/reducer.js
index d46106f6b..4da85fa4e 100644
--- a/modules/ppcp-settings/resources/js/data/payment/reducer.js
+++ b/modules/ppcp-settings/resources/js/data/payment/reducer.js
@@ -19,6 +19,7 @@ const defaultTransient = Object.freeze( {
// Persistent: Values that are loaded from the DB.
const defaultPersistent = Object.freeze( {
+ // Payment methods.
'ppcp-gateway': {},
venmo: {},
'pay-later': {},
@@ -37,6 +38,8 @@ const defaultPersistent = Object.freeze( {
'ppcp-multibanco': {},
'ppcp-pay-upon-invoice-gateway': {},
'ppcp-oxxo-gateway': {},
+
+ // Custom payment method properties.
paypalShowLogo: false,
threeDSecure: 'no-3d-secure',
fastlaneCardholderName: false,
From b2b0bb8d7af0bd1a7f9ba6c7acd63239b02cb220 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Fri, 14 Feb 2025 17:49:35 +0100
Subject: [PATCH 05/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Convert=20payment-st?=
=?UTF-8?q?ore=20hooks=20to=20new=20code=20pattern?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/payment/hooks.js | 109 ++++--------------
1 file changed, 25 insertions(+), 84 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/payment/hooks.js b/modules/ppcp-settings/resources/js/data/payment/hooks.js
index 5a330f1b2..582fd86f6 100644
--- a/modules/ppcp-settings/resources/js/data/payment/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/payment/hooks.js
@@ -37,7 +37,21 @@ const useStoreData = () => {
);
};
-const useHooks = () => {
+export const useStore = () => {
+ const { useTransient, dispatch } = useStoreData();
+ const { persist, refresh, setPersistent, changePaymentSettings } = dispatch;
+ const [ isReady ] = useTransient( 'isReady' );
+
+ return {
+ persist,
+ refresh,
+ setPersistent,
+ changePaymentSettings,
+ isReady,
+ };
+};
+
+export const usePaymentMethods = () => {
const { usePersistent } = useStoreData();
// PayPal checkout.
@@ -64,83 +78,6 @@ const useHooks = () => {
const [ pui ] = usePersistent( 'ppcp-pay-upon-invoice-gateway' );
const [ oxxo ] = usePersistent( 'ppcp-oxxo-gateway' );
- // Custom modal data.
- const [ paypalShowLogo ] = usePersistent( 'paypalShowLogo' );
- const [ threeDSecure ] = usePersistent( 'threeDSecure' );
- const [ fastlaneCardholderName ] = usePersistent(
- 'fastlaneCardholderName'
- );
- const [ fastlaneDisplayWatermark ] = usePersistent(
- 'fastlaneDisplayWatermark'
- );
-
- return {
- paypal,
- venmo,
- payLater,
- creditCard,
- advancedCreditCard,
- fastlane,
- applePay,
- googlePay,
- bancontact,
- blik,
- eps,
- ideal,
- mybank,
- p24,
- trustly,
- multibanco,
- pui,
- oxxo,
- paypalShowLogo,
- threeDSecure,
- fastlaneCardholderName,
- fastlaneDisplayWatermark,
- };
-};
-
-export const useStore = () => {
- const { useTransient, dispatch } = useStoreData();
- const { persist, refresh, setPersistent, changePaymentSettings } = dispatch;
- const [ isReady ] = useTransient( 'isReady' );
-
- return {
- persist,
- refresh,
- setPersistent,
- changePaymentSettings,
- isReady,
- };
-};
-
-export const usePaymentMethods = () => {
- const {
- // PayPal Checkout.
- paypal,
- venmo,
- payLater,
- creditCard,
-
- // Online card payments.
- advancedCreditCard,
- fastlane,
- applePay,
- googlePay,
-
- // Local APMs.
- bancontact,
- blik,
- eps,
- ideal,
- mybank,
- p24,
- trustly,
- multibanco,
- pui,
- oxxo,
- } = useHooks();
-
const payPalCheckout = [ paypal, venmo, payLater, creditCard ];
const onlineCardPayments = [
advancedCreditCard,
@@ -190,12 +127,16 @@ export const usePaymentMethods = () => {
};
export const usePaymentMethodsModal = () => {
- const {
- paypalShowLogo,
- threeDSecure,
- fastlaneCardholderName,
- fastlaneDisplayWatermark,
- } = useHooks();
+ const { usePersistent } = useStoreData();
+
+ const [ paypalShowLogo ] = usePersistent( 'paypalShowLogo' );
+ const [ threeDSecure ] = usePersistent( 'threeDSecure' );
+ const [ fastlaneCardholderName ] = usePersistent(
+ 'fastlaneCardholderName'
+ );
+ const [ fastlaneDisplayWatermark ] = usePersistent(
+ 'fastlaneDisplayWatermark'
+ );
return {
paypalShowLogo,
From fe0f17a9ce7d016ef110cb97c87bdfa7764e35f5 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Fri, 14 Feb 2025 17:55:45 +0100
Subject: [PATCH 06/23] =?UTF-8?q?=E2=9C=A8=20Create=20refresh=20actions=20?=
=?UTF-8?q?for=20all=20stores?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/_example/actions.js | 13 ++++++++++++
.../resources/js/data/common/actions-thunk.js | 13 ++++++++++++
.../js/data/pay-later-messaging/actions.js | 13 ++++++++++++
.../resources/js/data/payment/actions.js | 2 +-
.../resources/js/data/settings/actions.js | 13 ++++++++++++
.../resources/js/data/styling/actions.js | 13 ++++++++++++
.../resources/js/data/todos/actions.js | 21 ++++++++++++++++++-
7 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/_example/actions.js b/modules/ppcp-settings/resources/js/data/_example/actions.js
index f9cd9a556..51b516bb1 100644
--- a/modules/ppcp-settings/resources/js/data/_example/actions.js
+++ b/modules/ppcp-settings/resources/js/data/_example/actions.js
@@ -82,3 +82,16 @@ export function persist() {
} );
};
}
+
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStore();
+
+ select.persistentData();
+ };
+}
diff --git a/modules/ppcp-settings/resources/js/data/common/actions-thunk.js b/modules/ppcp-settings/resources/js/data/common/actions-thunk.js
index 8e7448af8..d49aa914a 100644
--- a/modules/ppcp-settings/resources/js/data/common/actions-thunk.js
+++ b/modules/ppcp-settings/resources/js/data/common/actions-thunk.js
@@ -27,6 +27,19 @@ export function persist() {
};
}
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStore();
+
+ select.persistentData();
+ };
+}
+
/**
* Side effect. Fetches the ISU-login URL for a sandbox account.
*
diff --git a/modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js b/modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js
index f9cd9a556..51b516bb1 100644
--- a/modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js
+++ b/modules/ppcp-settings/resources/js/data/pay-later-messaging/actions.js
@@ -82,3 +82,16 @@ export function persist() {
} );
};
}
+
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStore();
+
+ select.persistentData();
+ };
+}
diff --git a/modules/ppcp-settings/resources/js/data/payment/actions.js b/modules/ppcp-settings/resources/js/data/payment/actions.js
index d8398795a..dfa100f76 100644
--- a/modules/ppcp-settings/resources/js/data/payment/actions.js
+++ b/modules/ppcp-settings/resources/js/data/payment/actions.js
@@ -102,7 +102,7 @@ export function persist() {
*/
export function refresh() {
return ( { dispatch, select } ) => {
- dispatch.invalidateResolutionForStoreSelector( 'persistentData' );
+ dispatch.invalidateResolutionForStore();
select.persistentData();
};
diff --git a/modules/ppcp-settings/resources/js/data/settings/actions.js b/modules/ppcp-settings/resources/js/data/settings/actions.js
index 6633516bb..f99adae5a 100644
--- a/modules/ppcp-settings/resources/js/data/settings/actions.js
+++ b/modules/ppcp-settings/resources/js/data/settings/actions.js
@@ -84,3 +84,16 @@ export function persist() {
} );
};
}
+
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStore();
+
+ select.persistentData();
+ };
+}
diff --git a/modules/ppcp-settings/resources/js/data/styling/actions.js b/modules/ppcp-settings/resources/js/data/styling/actions.js
index 9e1639c7f..72d4d9ea7 100644
--- a/modules/ppcp-settings/resources/js/data/styling/actions.js
+++ b/modules/ppcp-settings/resources/js/data/styling/actions.js
@@ -82,3 +82,16 @@ export function persist() {
} );
};
}
+
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStore();
+
+ select.persistentData();
+ };
+}
diff --git a/modules/ppcp-settings/resources/js/data/todos/actions.js b/modules/ppcp-settings/resources/js/data/todos/actions.js
index 41ac372cd..864fe4173 100644
--- a/modules/ppcp-settings/resources/js/data/todos/actions.js
+++ b/modules/ppcp-settings/resources/js/data/todos/actions.js
@@ -39,6 +39,7 @@ export const setCompletedTodos = ( completedTodos ) => ( {
// Thunks
+// TODO: Possibly, this should be a resolver?
export function fetchTodos() {
return async () => {
const response = await apiFetch( { path: REST_PATH } );
@@ -46,9 +47,14 @@ export function fetchTodos() {
};
}
+/**
+ * Thunk action creator. Triggers the persistence of store data to the server.
+ *
+ * @return {Function} The thunk function.
+ */
export function persist() {
return async ( { select } ) => {
- return await apiFetch( {
+ await apiFetch( {
path: REST_PERSIST_PATH,
method: 'POST',
data: select.persistentData(),
@@ -56,6 +62,19 @@ export function persist() {
};
}
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStore();
+
+ select.persistentData();
+ };
+}
+
export function resetDismissedTodos() {
return async ( { dispatch } ) => {
try {
From 512574a9ad5f487f7d4602434dcfbf4bab6ec2b0 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:18:15 +0100
Subject: [PATCH 07/23] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20Impro?=
=?UTF-8?q?ve=20debug=20tools?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ppcp-settings/resources/js/data/debug.js | 94 +++++++++++++++----
1 file changed, 74 insertions(+), 20 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/debug.js b/modules/ppcp-settings/resources/js/data/debug.js
index 88bdf40ae..66530d7ec 100644
--- a/modules/ppcp-settings/resources/js/data/debug.js
+++ b/modules/ppcp-settings/resources/js/data/debug.js
@@ -18,6 +18,11 @@ export const addDebugTools = ( context, modules ) => {
if ( ! context.debug ) { return }
*/
+ const describe = ( fnName, fnInfo ) => {
+ // eslint-disable-next-line no-console
+ console.log( `\n%c${ fnName }:`, 'font-weight:bold', fnInfo, '\n\n' );
+ };
+
const debugApi = ( window.ppcpDebugger = window.ppcpDebugger || {} );
// Dump the current state of all our Redux stores.
@@ -51,45 +56,89 @@ export const addDebugTools = ( context, modules ) => {
// Reset all Redux stores to their initial state.
debugApi.resetStore = () => {
const stores = [];
- const { isConnected } = wp.data.select( CommonStoreName ).merchant();
- if ( isConnected ) {
- // Make sure the Onboarding wizard is "completed".
- const onboarding = wp.data.dispatch( OnboardingStoreName );
- onboarding.setPersistent( 'completed', true );
- onboarding.persist();
+ describe(
+ 'resetStore',
+ 'Reset all Redux stores to their DEFAULT state, without changing any server-side data. The default state is defined in the JS code.'
+ );
- // Reset all stores, except for the onboarding store.
- stores.push( CommonStoreName );
- stores.push( PaymentStoreName );
- stores.push( SettingsStoreName );
- stores.push( StylingStoreName );
- stores.push( TodosStoreName );
- } else {
- // Only reset the common & onboarding stores to restart the onboarding wizard.
- stores.push( CommonStoreName );
+ const { completed } = wp.data
+ .select( OnboardingStoreName )
+ .persistentData();
+
+ // Reset all stores, except for the onboarding store.
+ stores.push( CommonStoreName );
+ stores.push( PaymentStoreName );
+ stores.push( SettingsStoreName );
+ stores.push( StylingStoreName );
+ stores.push( TodosStoreName );
+
+ // Only reset the onboarding store when the wizard is not completed.
+ if ( ! completed ) {
stores.push( OnboardingStoreName );
}
stores.forEach( ( storeName ) => {
const store = wp.data.dispatch( storeName );
- // eslint-disable-next-line no-console
- console.log( `Reset store: ${ storeName }...` );
-
try {
store.reset();
- store.persist();
+
+ // eslint-disable-next-line no-console
+ console.log( `Done: Store '${ storeName }' reset` );
} catch ( error ) {
- console.error( ' ... Reset failed, skipping this store' );
+ console.error(
+ `Failed: Could not reset store '${ storeName }'`
+ );
}
} );
+
+ // eslint-disable-next-line no-console
+ console.log( '---- Complete ----\n\n' );
+ };
+
+ debugApi.refreshStore = () => {
+ const stores = [];
+
+ describe(
+ 'refreshStore',
+ 'Refreshes all Redux details with details provided by the server. This has a similar effect as reloading the page without saving'
+ );
+
+ stores.push( CommonStoreName );
+ stores.push( PaymentStoreName );
+ stores.push( SettingsStoreName );
+ stores.push( StylingStoreName );
+ stores.push( TodosStoreName );
+ stores.push( OnboardingStoreName );
+
+ stores.forEach( ( storeName ) => {
+ const store = wp.data.dispatch( storeName );
+
+ try {
+ store.refresh();
+
+ // eslint-disable-next-line no-console
+ console.log(
+ `Done: Store '${ storeName }' refreshed from REST`
+ );
+ } catch ( error ) {
+ console.error(
+ `Failed: Could not refresh store '${ storeName }' from REST`
+ );
+ }
+ } );
+
+ // eslint-disable-next-line no-console
+ console.log( '---- Complete ----\n\n' );
};
// Disconnect the merchant and display the onboarding wizard.
debugApi.disconnect = () => {
const common = wp.data.dispatch( CommonStoreName );
+ describe();
+
common.disconnectMerchant();
// eslint-disable-next-line no-console
@@ -102,6 +151,11 @@ export const addDebugTools = ( context, modules ) => {
debugApi.onboardingMode = ( state ) => {
const onboarding = wp.data.dispatch( OnboardingStoreName );
+ describe(
+ 'onboardingMode',
+ 'Toggle between onboarding wizard and the settings screen.'
+ );
+
onboarding.setPersistent( 'completed', ! state );
onboarding.persist();
};
From 2d3b37ee17a64455d606505f2be240e6cc0cc66c Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:18:34 +0100
Subject: [PATCH 08/23] =?UTF-8?q?=E2=9C=A8=20Add=20missing=20refresh=20act?=
=?UTF-8?q?ion=20to=20onboarding=20store?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/onboarding/actions.js | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/modules/ppcp-settings/resources/js/data/onboarding/actions.js b/modules/ppcp-settings/resources/js/data/onboarding/actions.js
index 0d2617095..70967168d 100644
--- a/modules/ppcp-settings/resources/js/data/onboarding/actions.js
+++ b/modules/ppcp-settings/resources/js/data/onboarding/actions.js
@@ -87,3 +87,16 @@ export function persist() {
}
};
}
+
+/**
+ * Thunk action creator. Forces a data refresh from the REST API, replacing the current Redux values.
+ *
+ * @return {Function} The thunk function.
+ */
+export function refresh() {
+ return ( { dispatch, select } ) => {
+ dispatch.invalidateResolutionForStore();
+
+ select.persistentData();
+ };
+}
From 85360ab7f1cb2395d53f1fbc4e58f918183d8b4f Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:20:00 +0100
Subject: [PATCH 09/23] =?UTF-8?q?=E2=9C=A8=20Add=20refresh=20hook=20to=20s?=
=?UTF-8?q?ample=20store?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modules/ppcp-settings/resources/js/data/_example/hooks.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/modules/ppcp-settings/resources/js/data/_example/hooks.js b/modules/ppcp-settings/resources/js/data/_example/hooks.js
index 21253d137..9df5d43d3 100644
--- a/modules/ppcp-settings/resources/js/data/_example/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/_example/hooks.js
@@ -39,9 +39,10 @@ const useStoreData = () => {
export const useStore = () => {
const { dispatch, useTransient } = useStoreData();
+ const { persist, refresh } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
- return { persist: dispatch.persist, isReady };
+ return { persist, refresh, isReady };
};
// TODO: Replace with real hook.
From 161df3a85f0271eb61eb4dc4e5c80f66bf06bff9 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:21:56 +0100
Subject: [PATCH 10/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Convert=20common=20h?=
=?UTF-8?q?ooks=20to=20new=20code=20pattern?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/common/hooks.js | 55 ++++++++++++++-----
1 file changed, 40 insertions(+), 15 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/common/hooks.js b/modules/ppcp-settings/resources/js/data/common/hooks.js
index 76a12cd2b..9a43989c1 100644
--- a/modules/ppcp-settings/resources/js/data/common/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/common/hooks.js
@@ -13,8 +13,32 @@ import { useCallback, useEffect, useMemo, useState } from '@wordpress/element';
import { createHooksForStore } from '../utils';
import { STORE_NAME } from './constants';
-const useHooks = () => {
+/**
+ * Single source of truth for access Redux details.
+ *
+ * This hook returns a stable API to access actions, selectors and special hooks to generate
+ * getter- and setters for transient or persistent properties.
+ *
+ * @return {{select, dispatch, useTransient, usePersistent}} Store data API.
+ */
+const useStoreData = () => {
+ const select = useSelect( ( selectors ) => selectors( STORE_NAME ), [] );
+ const dispatch = useDispatch( STORE_NAME );
const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
+
+ return useMemo(
+ () => ( {
+ select,
+ dispatch,
+ useTransient,
+ usePersistent,
+ } ),
+ [ select, dispatch, useTransient, usePersistent ]
+ );
+};
+
+const useHooks = () => {
+ const { useTransient, usePersistent, dispatch, select } = useStoreData();
const {
persist,
sandboxOnboardingUrl,
@@ -23,7 +47,7 @@ const useHooks = () => {
authenticateWithOAuth,
startWebhookSimulation,
checkWebhookSimulationState,
- } = useDispatch( STORE_NAME );
+ } = dispatch;
// Transient accessors.
const [ isReady ] = useTransient( 'isReady' );
@@ -38,18 +62,9 @@ const useHooks = () => {
);
// Read-only properties.
- const wooSettings = useSelect(
- ( select ) => select( STORE_NAME ).wooSettings(),
- []
- );
- const features = useSelect(
- ( select ) => select( STORE_NAME ).features(),
- []
- );
- const webhooks = useSelect(
- ( select ) => select( STORE_NAME ).webhooks(),
- []
- );
+ const wooSettings = select.wooSettings();
+ const features = select.features();
+ const webhooks = select.webhooks();
const savePersistent = async ( setter, value ) => {
setter( value );
@@ -82,6 +97,14 @@ const useHooks = () => {
};
};
+export const useStore = () => {
+ const { dispatch, useTransient } = useStoreData();
+ const { persist, refresh } = dispatch;
+ const [ isReady ] = useTransient( 'isReady' );
+
+ return { persist, refresh, isReady };
+};
+
export const useSandbox = () => {
const { isSandboxMode, setSandboxMode, sandboxOnboardingUrl } = useHooks();
@@ -204,7 +227,9 @@ export const useActiveHighlight = () => {
return { activeHighlight, setActiveHighlight };
};
-// -- Not using the `useHooks()` data provider --
+/*
+ * Busy state management hooks
+ */
export const useBusyState = () => {
const { startActivity, stopActivity } = useDispatch( STORE_NAME );
From 0867a3cc6360f3b3d8dc7200ee2256d655fcd6d9 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:24:12 +0100
Subject: [PATCH 11/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Remove=20duplicate?=
=?UTF-8?q?=20=E2=80=9Ccommon.isReady=E2=80=9D=20accessor?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modules/ppcp-settings/resources/js/Components/App.js | 2 +-
.../js/Components/Screens/Settings/Tabs/TabOverview.js | 2 +-
modules/ppcp-settings/resources/js/data/common/hooks.js | 5 +----
3 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/Components/App.js b/modules/ppcp-settings/resources/js/Components/App.js
index 1febe8674..6441d0a51 100644
--- a/modules/ppcp-settings/resources/js/Components/App.js
+++ b/modules/ppcp-settings/resources/js/Components/App.js
@@ -11,8 +11,8 @@ import { getQuery } from '../utils/navigation';
const SettingsApp = () => {
const { isReady: onboardingIsReady, completed: onboardingCompleted } =
OnboardingHooks.useSteps();
+ const { isReady: merchantIsReady } = CommonHooks.useStore();
const {
- isReady: merchantIsReady,
merchant: { isSendOnlyCountry },
} = CommonHooks.useMerchantInfo();
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
index a5a1014e6..de1c16971 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
@@ -28,7 +28,7 @@ import SpinnerOverlay from '../../../ReusableComponents/SpinnerOverlay';
const TabOverview = () => {
const { isReady: areTodosReady } = TodosHooks.useTodos();
- const { isReady: merchantIsReady } = CommonHooks.useMerchantInfo();
+ const { isReady: merchantIsReady } = CommonHooks.useStore();
if ( ! areTodosReady || ! merchantIsReady ) {
return ;
diff --git a/modules/ppcp-settings/resources/js/data/common/hooks.js b/modules/ppcp-settings/resources/js/data/common/hooks.js
index 9a43989c1..49e5736a1 100644
--- a/modules/ppcp-settings/resources/js/data/common/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/common/hooks.js
@@ -50,7 +50,6 @@ const useHooks = () => {
} = dispatch;
// Transient accessors.
- const [ isReady ] = useTransient( 'isReady' );
const [ activeModal, setActiveModal ] = useTransient( 'activeModal' );
const [ activeHighlight, setActiveHighlight ] =
useTransient( 'activeHighlight' );
@@ -72,7 +71,6 @@ const useHooks = () => {
};
return {
- isReady,
activeModal,
setActiveModal,
activeHighlight,
@@ -162,7 +160,7 @@ export const useWebhooks = () => {
};
export const useMerchantInfo = () => {
- const { isReady, features } = useHooks();
+ const { features } = useHooks();
const merchant = useMerchant();
const { refreshMerchantData, setMerchant } = useDispatch( STORE_NAME );
@@ -187,7 +185,6 @@ export const useMerchantInfo = () => {
}, [ refreshMerchantData, setMerchant ] );
return {
- isReady,
merchant, // Merchant details
features, // Eligible merchant features
verifyLoginStatus, // Callback
From a9bba9fb92e86227fa9decee4bcb7ecf80949ba3 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:28:35 +0100
Subject: [PATCH 12/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Convert=20settings?=
=?UTF-8?q?=20hooks=20to=20new=20code=20pattern?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/settings/hooks.js | 42 ++++++++++++++-----
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/settings/hooks.js b/modules/ppcp-settings/resources/js/data/settings/hooks.js
index f161ee48e..a79f1fc6d 100644
--- a/modules/ppcp-settings/resources/js/data/settings/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/settings/hooks.js
@@ -6,17 +6,38 @@
*
* @file
*/
-import { useDispatch } from '@wordpress/data';
+import { useDispatch, useSelect } from '@wordpress/data';
import { STORE_NAME } from './constants';
import { createHooksForStore } from '../utils';
+import { useMemo } from '@wordpress/element';
+
+/**
+ * Single source of truth for access Redux details.
+ *
+ * This hook returns a stable API to access actions, selectors and special hooks to generate
+ * getter- and setters for transient or persistent properties.
+ *
+ * @return {{select, dispatch, useTransient, usePersistent}} Store data API.
+ */
+const useStoreData = () => {
+ const select = useSelect( ( selectors ) => selectors( STORE_NAME ), [] );
+ const dispatch = useDispatch( STORE_NAME );
+ const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
+
+ return useMemo(
+ () => ( {
+ select,
+ dispatch,
+ useTransient,
+ usePersistent,
+ } ),
+ [ select, dispatch, useTransient, usePersistent ]
+ );
+};
const useHooks = () => {
- const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
- const { persist } = useDispatch( STORE_NAME );
-
- // Read-only flags and derived state.
- const [ isReady ] = useTransient( 'isReady' );
+ const { usePersistent } = useStoreData();
// Persistent accessors.
const [ invoicePrefix, setInvoicePrefix ] =
@@ -47,8 +68,6 @@ const useHooks = () => {
usePersistent( 'disabledCards' );
return {
- persist,
- isReady,
invoicePrefix,
setInvoicePrefix,
authorizeOnly,
@@ -79,8 +98,11 @@ const useHooks = () => {
};
export const useStore = () => {
- const { persist, isReady } = useHooks();
- return { persist, isReady };
+ const { dispatch, useTransient } = useStoreData();
+ const { persist, refresh } = dispatch;
+ const [ isReady ] = useTransient( 'isReady' );
+
+ return { persist, refresh, isReady };
};
export const useSettings = () => {
From 1bebfe5e62484a0b99912d884e1ad78a5ff97b67 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:31:21 +0100
Subject: [PATCH 13/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Convert=20styling=20?=
=?UTF-8?q?hooks=20to=20new=20code=20pattern?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/styling/hooks.js | 40 +++++++++++++++----
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/styling/hooks.js b/modules/ppcp-settings/resources/js/data/styling/hooks.js
index 8227d0124..a9d7bcbd6 100644
--- a/modules/ppcp-settings/resources/js/data/styling/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/styling/hooks.js
@@ -7,7 +7,7 @@
* @file
*/
-import { useCallback } from '@wordpress/element';
+import { useCallback, useMemo } from '@wordpress/element';
import { useDispatch, useSelect } from '@wordpress/data';
import { createHooksForStore } from '../utils';
@@ -21,12 +21,35 @@ import {
STYLING_SHAPES,
} from './configuration';
+/**
+ * Single source of truth for access Redux details.
+ *
+ * This hook returns a stable API to access actions, selectors and special hooks to generate
+ * getter- and setters for transient or persistent properties.
+ *
+ * @return {{select, dispatch, useTransient, usePersistent}} Store data API.
+ */
+const useStoreData = () => {
+ const select = useSelect( ( selectors ) => selectors( STORE_NAME ), [] );
+ const dispatch = useDispatch( STORE_NAME );
+ const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
+
+ return useMemo(
+ () => ( {
+ select,
+ dispatch,
+ useTransient,
+ usePersistent,
+ } ),
+ [ select, dispatch, useTransient, usePersistent ]
+ );
+};
+
const useHooks = () => {
- const { useTransient } = createHooksForStore( STORE_NAME );
- const { persist, setPersistent } = useDispatch( STORE_NAME );
+ const { useTransient, dispatch } = useStoreData();
+ const { setPersistent } = dispatch;
// Transient accessors.
- const [ isReady ] = useTransient( 'isReady' );
const [ location, setLocation ] = useTransient( 'location' );
// Persistent accessors.
@@ -61,8 +84,6 @@ const useHooks = () => {
);
return {
- persist,
- isReady,
location,
setLocation,
getLocationProp,
@@ -71,8 +92,11 @@ const useHooks = () => {
};
export const useStore = () => {
- const { persist, isReady } = useHooks();
- return { persist, isReady };
+ const { dispatch, useTransient } = useStoreData();
+ const { persist, refresh } = dispatch;
+ const [ isReady ] = useTransient( 'isReady' );
+
+ return { persist, refresh, isReady };
};
export const useStylingLocation = () => {
From e5f83756ab7b71d8219e256317bacfcb4fa5013a Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:33:00 +0100
Subject: [PATCH 14/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Convert=20todo-store?=
=?UTF-8?q?=20hooks=20to=20new=20code=20pattern?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/todos/hooks.js | 42 ++++++++++++++-----
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/todos/hooks.js b/modules/ppcp-settings/resources/js/data/todos/hooks.js
index 7fc5da5c1..79fc2e19a 100644
--- a/modules/ppcp-settings/resources/js/data/todos/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/todos/hooks.js
@@ -10,6 +10,31 @@
import { useSelect, useDispatch } from '@wordpress/data';
import { STORE_NAME } from './constants';
import { createHooksForStore } from '../utils';
+import { useMemo } from '@wordpress/element';
+
+/**
+ * Single source of truth for access Redux details.
+ *
+ * This hook returns a stable API to access actions, selectors and special hooks to generate
+ * getter- and setters for transient or persistent properties.
+ *
+ * @return {{select, dispatch, useTransient, usePersistent}} Store data API.
+ */
+const useStoreData = () => {
+ const select = useSelect( ( selectors ) => selectors( STORE_NAME ), [] );
+ const dispatch = useDispatch( STORE_NAME );
+ const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
+
+ return useMemo(
+ () => ( {
+ select,
+ dispatch,
+ useTransient,
+ usePersistent,
+ } ),
+ [ select, dispatch, useTransient, usePersistent ]
+ );
+};
const ensureArray = ( value ) => {
if ( ! value ) {
@@ -19,12 +44,8 @@ const ensureArray = ( value ) => {
};
const useHooks = () => {
- const { useTransient } = createHooksForStore( STORE_NAME );
- const { fetchTodos, setDismissedTodos, setCompletedTodos, persist } =
- useDispatch( STORE_NAME );
-
- // Read-only flags and derived state.
- const [ isReady ] = useTransient( 'isReady' );
+ const { dispatch } = useStoreData();
+ const { fetchTodos, setDismissedTodos, setCompletedTodos } = dispatch;
// Get todos data from store
const { todos, dismissedTodos, completedTodos } = useSelect( ( select ) => {
@@ -62,8 +83,6 @@ const useHooks = () => {
);
return {
- persist,
- isReady,
todos: filteredTodos,
dismissedTodos,
completedTodos,
@@ -74,8 +93,11 @@ const useHooks = () => {
};
export const useStore = () => {
- const { persist, isReady } = useHooks();
- return { persist, isReady };
+ const { dispatch, useTransient } = useStoreData();
+ const { persist, refresh } = dispatch;
+ const [ isReady ] = useTransient( 'isReady' );
+
+ return { persist, refresh, isReady };
};
export const useTodos = () => {
From b9785d17055c0f60a7eee56e3f6a5023129f70b5 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 13:43:41 +0100
Subject: [PATCH 15/23] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20Add?=
=?UTF-8?q?=20simple=20filter-callback=20for=20dumpStore?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ppcp-settings/resources/js/data/debug.js | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/debug.js b/modules/ppcp-settings/resources/js/data/debug.js
index 66530d7ec..286285892 100644
--- a/modules/ppcp-settings/resources/js/data/debug.js
+++ b/modules/ppcp-settings/resources/js/data/debug.js
@@ -26,7 +26,7 @@ export const addDebugTools = ( context, modules ) => {
const debugApi = ( window.ppcpDebugger = window.ppcpDebugger || {} );
// Dump the current state of all our Redux stores.
- debugApi.dumpStore = async () => {
+ debugApi.dumpStore = async ( cbFilter = null ) => {
/* eslint-disable no-console */
if ( ! console?.groupCollapsed ) {
console.error( 'console.groupCollapsed is not supported.' );
@@ -39,11 +39,19 @@ export const addDebugTools = ( context, modules ) => {
console.group( `[STORE] ${ storeSelector }` );
const dumpStore = ( selector ) => {
- const contents = wp.data.select( storeName )[ selector ]();
+ let contents = wp.data.select( storeName )[ selector ]();
- console.groupCollapsed( `.${ selector }()` );
- console.table( contents );
- console.groupEnd();
+ if ( cbFilter ) {
+ contents = cbFilter( contents, selector, storeName );
+
+ if ( undefined !== contents && null !== contents ) {
+ console.log( `.${ selector }() [filtered]`, contents );
+ }
+ } else {
+ console.groupCollapsed( `.${ selector }()` );
+ console.table( contents );
+ console.groupEnd();
+ }
};
Object.keys( module.selectors ).forEach( dumpStore );
From 180e47fa0a68d5a8d50c098c82b04f4a33480daf Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:07:00 +0100
Subject: [PATCH 16/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Fix=20hooks=20in=20t?=
=?UTF-8?q?he=20TabOverview=20component?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Screens/Settings/Tabs/TabOverview.js | 29 ++++++++++++-------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
index de1c16971..238cc1c68 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
@@ -12,11 +12,12 @@ import {
import { Content, ContentWrapper } from '../../../ReusableComponents/Elements';
import SettingsCard from '../../../ReusableComponents/SettingsCard';
import { TITLE_BADGE_POSITIVE } from '../../../ReusableComponents/TitleBadge';
-import { useTodos } from '../../../../data/todos/hooks';
-import { useMerchantInfo } from '../../../../data/common/hooks';
-import { STORE_NAME as COMMON_STORE_NAME } from '../../../../data/common';
-import { STORE_NAME as TODOS_STORE_NAME } from '../../../../data/todos';
-import { CommonHooks, TodosHooks } from '../../../../data';
+import {
+ CommonStoreName,
+ TodosStoreName,
+ CommonHooks,
+ TodosHooks,
+} from '../../../../data';
import { getFeatures } from '../Components/Overview/features-config';
@@ -27,9 +28,13 @@ import {
import SpinnerOverlay from '../../../ReusableComponents/SpinnerOverlay';
const TabOverview = () => {
- const { isReady: areTodosReady } = TodosHooks.useTodos();
+ const { isReady: areTodosReady } = TodosHooks.useStore();
const { isReady: merchantIsReady } = CommonHooks.useStore();
+ // TODO: Workaround before we implement the standard "persistentData" resolver.
+ // Calling this hook ensures that todos are loaded from the REST API at this point.
+ const {} = TodosHooks.useTodos();
+
if ( ! areTodosReady || ! merchantIsReady ) {
return ;
}
@@ -47,11 +52,12 @@ export default TabOverview;
const OverviewTodos = () => {
const [ isResetting, setIsResetting ] = useState( false );
- const { todos, isReady: areTodosReady, dismissTodo } = useTodos();
+ const { todos, dismissTodo } = TodosHooks.useTodos();
+ const { isReady: areTodosReady } = TodosHooks.useStore();
const { setActiveModal, setActiveHighlight } =
- useDispatch( COMMON_STORE_NAME );
+ useDispatch( CommonStoreName );
const { resetDismissedTodos, setDismissedTodos } =
- useDispatch( TODOS_STORE_NAME );
+ useDispatch( TodosStoreName );
const { createSuccessNotice } = useDispatch( noticesStore );
const showTodos = areTodosReady && todos.length > 0;
@@ -118,9 +124,10 @@ const OverviewTodos = () => {
const OverviewFeatures = () => {
const [ isRefreshing, setIsRefreshing ] = useState( false );
- const { merchant, features: merchantFeatures } = useMerchantInfo();
+ const { merchant, features: merchantFeatures } =
+ CommonHooks.useMerchantInfo();
const { refreshFeatureStatuses, setActiveModal } =
- useDispatch( COMMON_STORE_NAME );
+ useDispatch( CommonStoreName );
const { createSuccessNotice, createErrorNotice } =
useDispatch( noticesStore );
From afcadb9508803f4eea1b516efaae4615a9e91161 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:08:07 +0100
Subject: [PATCH 17/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Fix=20hooks=20in=20t?=
=?UTF-8?q?he=20TabOverview=20component?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modules/ppcp-settings/resources/js/data/todos/hooks.js | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/todos/hooks.js b/modules/ppcp-settings/resources/js/data/todos/hooks.js
index 79fc2e19a..57172e24b 100644
--- a/modules/ppcp-settings/resources/js/data/todos/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/todos/hooks.js
@@ -101,9 +101,8 @@ export const useStore = () => {
};
export const useTodos = () => {
- const { todos, fetchTodos, dismissTodo, setTodoCompleted, isReady } =
- useHooks();
- return { todos, fetchTodos, dismissTodo, setTodoCompleted, isReady };
+ const { todos, fetchTodos, dismissTodo, setTodoCompleted } = useHooks();
+ return { todos, fetchTodos, dismissTodo, setTodoCompleted };
};
export const useDismissedTodos = () => {
From 7185f5190ffe02aae6ecd4fd80086463386b072e Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:08:47 +0100
Subject: [PATCH 18/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Move=20data=20sanita?=
=?UTF-8?q?tion=20logic=20into=20selector?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/todos/hooks.js | 20 ++++---------------
.../resources/js/data/todos/selectors.js | 16 ++++++++++++---
2 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/todos/hooks.js b/modules/ppcp-settings/resources/js/data/todos/hooks.js
index 57172e24b..f7bae751b 100644
--- a/modules/ppcp-settings/resources/js/data/todos/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/todos/hooks.js
@@ -36,26 +36,14 @@ const useStoreData = () => {
);
};
-const ensureArray = ( value ) => {
- if ( ! value ) {
- return [];
- }
- return Array.isArray( value ) ? value : Object.values( value );
-};
-
const useHooks = () => {
- const { dispatch } = useStoreData();
+ const { dispatch, select } = useStoreData();
const { fetchTodos, setDismissedTodos, setCompletedTodos } = dispatch;
// Get todos data from store
- const { todos, dismissedTodos, completedTodos } = useSelect( ( select ) => {
- const store = select( STORE_NAME );
- return {
- todos: ensureArray( store.getTodos() ),
- dismissedTodos: ensureArray( store.getDismissedTodos() ),
- completedTodos: ensureArray( store.getCompletedTodos() ),
- };
- }, [] );
+ const todos = select.getTodos();
+ const dismissedTodos = select.getDismissedTodos();
+ const completedTodos = select.getCompletedTodos();
const dismissedSet = new Set( dismissedTodos );
diff --git a/modules/ppcp-settings/resources/js/data/todos/selectors.js b/modules/ppcp-settings/resources/js/data/todos/selectors.js
index 2f42c6ffc..1066ba3a8 100644
--- a/modules/ppcp-settings/resources/js/data/todos/selectors.js
+++ b/modules/ppcp-settings/resources/js/data/todos/selectors.js
@@ -11,7 +11,17 @@ const EMPTY_OBJ = Object.freeze( {} );
const EMPTY_ARR = Object.freeze( [] );
const getState = ( state ) => state || EMPTY_OBJ;
+const getArray = ( value ) => {
+ if ( Array.isArray( value ) ) {
+ return value;
+ }
+ if ( value ) {
+ return Object.values( value );
+ }
+ return EMPTY_ARR;
+};
+// TODO: Implement a persistentData resolver!
export const persistentData = ( state ) => {
return getState( state ).data || EMPTY_OBJ;
};
@@ -23,15 +33,15 @@ export const transientData = ( state ) => {
export const getTodos = ( state ) => {
const todos = state?.todos || persistentData( state ).todos;
- return todos || EMPTY_ARR;
+ return getArray( todos );
};
export const getDismissedTodos = ( state ) => {
const dismissed =
state?.dismissedTodos || persistentData( state ).dismissedTodos;
- return dismissed || EMPTY_ARR;
+ return getArray( dismissed );
};
export const getCompletedTodos = ( state ) => {
- return state?.completedTodos || EMPTY_ARR; // Only look at root state, not persistent data
+ return getArray( state?.completedTodos ); // Only look at root state, not persistent data
};
From 2477e4d357a102858228eb45ca96ab21a8834004 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:09:12 +0100
Subject: [PATCH 19/23] =?UTF-8?q?=E2=9C=A8=20Add=20missing=20reset=20actio?=
=?UTF-8?q?n=20to=20todo=20store?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/data/todos/action-types.js | 6 +++
.../resources/js/data/todos/actions.js | 42 +++++++++++++++++--
.../resources/js/data/todos/reducer.js | 16 +++++++
3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/data/todos/action-types.js b/modules/ppcp-settings/resources/js/data/todos/action-types.js
index 66d92218a..17bbe8a0f 100644
--- a/modules/ppcp-settings/resources/js/data/todos/action-types.js
+++ b/modules/ppcp-settings/resources/js/data/todos/action-types.js
@@ -5,6 +5,12 @@
*/
export default {
+ /**
+ * Resets the store state to its initial values.
+ * Used when needing to clear all store data.
+ */
+ RESET: 'ppcp/todos/RESET',
+
// Transient data
SET_TRANSIENT: 'ppcp/todos/SET_TRANSIENT',
SET_COMPLETED_TODOS: 'ppcp/todos/SET_COMPLETED_TODOS',
diff --git a/modules/ppcp-settings/resources/js/data/todos/actions.js b/modules/ppcp-settings/resources/js/data/todos/actions.js
index 864fe4173..25b6d7647 100644
--- a/modules/ppcp-settings/resources/js/data/todos/actions.js
+++ b/modules/ppcp-settings/resources/js/data/todos/actions.js
@@ -17,11 +17,47 @@ import {
REST_RESET_DISMISSED_TODOS_PATH,
} from './constants';
-export const setIsReady = ( isReady ) => ( {
- type: ACTION_TYPES.SET_TRANSIENT,
- payload: { isReady },
+/**
+ * Special. Resets all values in the store to initial defaults.
+ *
+ * @return {Object} The action.
+ */
+export const reset = () => ( {
+ type: ACTION_TYPES.RESET,
} );
+/**
+ * Generic transient-data updater.
+ *
+ * @param {string} prop Name of the property to update.
+ * @param {any} value The new value of the property.
+ * @return {Object} The action.
+ */
+export const setTransient = ( prop, value ) => ( {
+ type: ACTION_TYPES.SET_TRANSIENT,
+ payload: { [ prop ]: value },
+} );
+
+/**
+ * Generic persistent-data updater.
+ *
+ * @param {string} prop Name of the property to update.
+ * @param {any} value The new value of the property.
+ * @return {Object} The action.
+ */
+export const setPersistent = ( prop, value ) => ( {
+ type: ACTION_TYPES.SET_PERSISTENT,
+ payload: { [ prop ]: value },
+} );
+
+/**
+ * Transient. Marks the store as "ready", i.e., fully initialized.
+ *
+ * @param {boolean} isReady Whether the store is ready
+ * @return {Object} The action.
+ */
+export const setIsReady = ( isReady ) => setTransient( 'isReady', isReady );
+
export const setTodos = ( todos ) => ( {
type: ACTION_TYPES.SET_TODOS,
payload: todos,
diff --git a/modules/ppcp-settings/resources/js/data/todos/reducer.js b/modules/ppcp-settings/resources/js/data/todos/reducer.js
index 6f4c74d46..f3cc412ac 100644
--- a/modules/ppcp-settings/resources/js/data/todos/reducer.js
+++ b/modules/ppcp-settings/resources/js/data/todos/reducer.js
@@ -52,6 +52,21 @@ const reducer = createReducer( defaultTransient, defaultPersistent, {
[ ACTION_TYPES.SET_TRANSIENT ]: ( state, payload ) =>
changeTransient( state, payload ),
+ /**
+ * Resets state to defaults while maintaining initialization status
+ *
+ * @param {Object} state Current state
+ * @return {Object} Reset state
+ */
+ [ ACTION_TYPES.RESET ]: ( state ) => {
+ const cleanState = changeTransient(
+ changePersistent( state, defaultPersistent ),
+ defaultTransient
+ );
+ cleanState.isReady = true; // Keep initialization flag
+ return cleanState;
+ },
+
/**
* Updates todos list
*
@@ -99,6 +114,7 @@ const reducer = createReducer( defaultTransient, defaultPersistent, {
},
/**
+ * TODO: This is not used anywhere. Remove "SET_TODOS" and use this resolver instead.
* Initializes persistent state with data from the server
*
* @param {Object} state Current state
From 480d15a7fb127ba794e8c1fe5be3b56fb1c6551b Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:17:37 +0100
Subject: [PATCH 20/23] =?UTF-8?q?=E2=9C=A8=20Implement=20a=20full-store-re?=
=?UTF-8?q?fresh=20hook?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/hooks/useSaveSettings.js | 68 ++++++++++---------
1 file changed, 35 insertions(+), 33 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js b/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js
index 7237aa4df..5c51866e6 100644
--- a/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js
+++ b/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js
@@ -12,48 +12,41 @@ import {
export const useSaveSettings = () => {
const { withActivity } = CommonHooks.useBusyState();
- const { persist: persistPayment } = PaymentHooks.useStore();
- const { persist: persistSettings } = SettingsHooks.useStore();
- const { persist: persistStyling } = StylingHooks.useStore();
- const { persist: persistTodos } = TodosHooks.useStore();
- const { persist: persistPayLaterMessaging } =
- PayLaterMessagingHooks.useStore();
+ const paymentStore = PaymentHooks.useStore();
+ const settingsStore = SettingsHooks.useStore();
+ const stylingStore = StylingHooks.useStore();
+ const todosStore = TodosHooks.useStore();
+ const payLaterStore = PayLaterMessagingHooks.useStore();
- const persistActions = useMemo(
+ const storeActions = useMemo(
() => [
{
- key: 'persist-methods',
- message: 'Save payment methods',
- action: persistPayment,
+ key: 'methods',
+ message: 'Process payment methods',
+ store: paymentStore,
},
{
- key: 'persist-settings',
- message: 'Save the settings',
- action: persistSettings,
+ key: 'settings',
+ message: 'Process the settings',
+ store: settingsStore,
},
{
- key: 'persist-styling',
- message: 'Save styling details',
- action: persistStyling,
+ key: 'styling',
+ message: 'Process styling details',
+ store: stylingStore,
},
{
- key: 'persist-todos',
- message: 'Save todos state',
- action: persistTodos,
+ key: 'todos',
+ message: 'Process todos state',
+ store: todosStore,
},
{
- key: 'persist-pay-later-messaging',
- message: 'Save pay later messaging details',
- action: persistPayLaterMessaging,
+ key: 'pay-later-messaging',
+ message: 'Process pay later messaging details',
+ store: payLaterStore,
},
],
- [
- persistPayLaterMessaging,
- persistPayment,
- persistSettings,
- persistStyling,
- persistTodos,
- ]
+ [ payLaterStore, paymentStore, settingsStore, stylingStore, todosStore ]
);
const persistAll = useCallback( () => {
@@ -65,10 +58,19 @@ export const useSaveSettings = () => {
*/
document.getElementById( 'configurator-publishButton' )?.click();
- persistActions.forEach( ( { key, message, action } ) => {
- withActivity( key, message, action );
+ storeActions.forEach( ( { key, message, store } ) => {
+ withActivity( `persist-${ key }`, message, store.persist );
} );
- }, [ persistActions, withActivity ] );
+ }, [ storeActions, withActivity ] );
- return { persistAll };
+ const refreshAll = useCallback( () => {
+ storeActions.forEach( ( { key, message, store } ) => {
+ withActivity( `refresh-${ key }`, message, store.refresh );
+ } );
+ }, [ storeActions, withActivity ] );
+
+ return {
+ persistAll,
+ refreshAll,
+ };
};
From 68e3cad0e87ffbf2a137cefa99b3729f74b019ce Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:19:01 +0100
Subject: [PATCH 21/23] =?UTF-8?q?=F0=9F=9A=9A=20Rename=20a=20hook=20as=20i?=
=?UTF-8?q?ts=20responsibility=20changed?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../js/Components/Screens/Settings/Components/Navigation.js | 4 ++--
.../js/hooks/{useSaveSettings.js => useStoreManager.js} | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
rename modules/ppcp-settings/resources/js/hooks/{useSaveSettings.js => useStoreManager.js} (97%)
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Navigation.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Navigation.js
index 6ea843c67..1b06eb222 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Navigation.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Navigation.js
@@ -3,7 +3,7 @@ import { __ } from '@wordpress/i18n';
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
import TopNavigation from '../../../ReusableComponents/TopNavigation';
-import { useSaveSettings } from '../../../../hooks/useSaveSettings';
+import { useStoreManager } from '../../../../hooks/useStoreManager';
import { CommonHooks } from '../../../../data';
import TabBar from '../../../ReusableComponents/TabBar';
import classNames from 'classnames';
@@ -20,7 +20,7 @@ const SettingsNavigation = ( {
activePanel,
setActivePanel,
} ) => {
- const { persistAll } = useSaveSettings();
+ const { persistAll } = useStoreManager();
const title = __( 'PayPal Payments', 'woocommerce-paypal-payments' );
diff --git a/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js b/modules/ppcp-settings/resources/js/hooks/useStoreManager.js
similarity index 97%
rename from modules/ppcp-settings/resources/js/hooks/useSaveSettings.js
rename to modules/ppcp-settings/resources/js/hooks/useStoreManager.js
index 5c51866e6..190b2ac88 100644
--- a/modules/ppcp-settings/resources/js/hooks/useSaveSettings.js
+++ b/modules/ppcp-settings/resources/js/hooks/useStoreManager.js
@@ -9,7 +9,7 @@ import {
TodosHooks,
} from '../data';
-export const useSaveSettings = () => {
+export const useStoreManager = () => {
const { withActivity } = CommonHooks.useBusyState();
const paymentStore = PaymentHooks.useStore();
From 274875ccdeac26b4afd64e3a41a43ad1ba0bdfa7 Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:19:50 +0100
Subject: [PATCH 22/23] =?UTF-8?q?=E2=9C=A8=20Refresh=20Redux=20data=20afte?=
=?UTF-8?q?r=20manual=20authentication?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../resources/js/hooks/useHandleConnections.js | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/hooks/useHandleConnections.js b/modules/ppcp-settings/resources/js/hooks/useHandleConnections.js
index e605b61ef..e98345149 100644
--- a/modules/ppcp-settings/resources/js/hooks/useHandleConnections.js
+++ b/modules/ppcp-settings/resources/js/hooks/useHandleConnections.js
@@ -4,6 +4,7 @@ import { useState, useEffect, useCallback, useRef } from '@wordpress/element';
import { store as noticesStore } from '@wordpress/notices';
import { CommonHooks, OnboardingHooks } from '../data';
+import { useStoreManager } from './useStoreManager';
const PAYPAL_PARTNER_SDK_URL =
'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js';
@@ -30,7 +31,7 @@ export const useHandleOnboardingButton = ( isSandbox ) => {
const { sandboxOnboardingUrl } = CommonHooks.useSandbox();
const { productionOnboardingUrl } = CommonHooks.useProduction();
const products = OnboardingHooks.useDetermineProducts();
- const { withActivity, startActivity } = CommonHooks.useBusyState();
+ const { startActivity } = CommonHooks.useBusyState();
const { authenticateWithOAuth } = CommonHooks.useAuthentication();
const [ onboardingUrl, setOnboardingUrl ] = useState( '' );
const [ scriptLoaded, setScriptLoaded ] = useState( false );
@@ -134,7 +135,7 @@ export const useHandleOnboardingButton = ( isSandbox ) => {
// Ensure the onComplete handler is not removed by a PayPal init script.
timerRef.current = setInterval( addHandler, 250 );
},
- [ authenticateWithOAuth, withActivity ]
+ [ authenticateWithOAuth, startActivity ]
);
const removeCompleteHandler = useCallback( () => {
@@ -161,6 +162,7 @@ const useConnectionBase = () => {
useDispatch( noticesStore );
const { verifyLoginStatus } = CommonHooks.useMerchantInfo();
const { withActivity } = CommonHooks.useBusyState();
+ const { refreshAll } = useStoreManager();
return {
handleFailed: ( res, genericMessage ) => {
@@ -178,6 +180,7 @@ const useConnectionBase = () => {
if ( loginSuccessful ) {
createSuccessNotice( MESSAGES.CONNECTED );
await setCompleted( true );
+ refreshAll();
} else {
createErrorNotice( MESSAGES.LOGIN_FAILED );
}
From 845e6b876abf5b95a9de392f0baf2e75834caece Mon Sep 17 00:00:00 2001
From: Philipp Stracker
Date: Mon, 17 Feb 2025 14:37:49 +0100
Subject: [PATCH 23/23] =?UTF-8?q?=E2=9C=A8=20Load=20persistent=20data=20on?=
=?UTF-8?q?=20first=20store=20access?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../js/Components/Screens/Settings/Tabs/TabOverview.js | 4 ----
modules/ppcp-settings/resources/js/data/_example/hooks.js | 7 ++++++-
modules/ppcp-settings/resources/js/data/common/hooks.js | 7 ++++++-
modules/ppcp-settings/resources/js/data/payment/hooks.js | 7 ++++++-
modules/ppcp-settings/resources/js/data/settings/hooks.js | 7 ++++++-
modules/ppcp-settings/resources/js/data/styling/hooks.js | 8 +++++++-
modules/ppcp-settings/resources/js/data/todos/hooks.js | 7 ++++++-
7 files changed, 37 insertions(+), 10 deletions(-)
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
index 238cc1c68..929b55df4 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
@@ -31,10 +31,6 @@ const TabOverview = () => {
const { isReady: areTodosReady } = TodosHooks.useStore();
const { isReady: merchantIsReady } = CommonHooks.useStore();
- // TODO: Workaround before we implement the standard "persistentData" resolver.
- // Calling this hook ensures that todos are loaded from the REST API at this point.
- const {} = TodosHooks.useTodos();
-
if ( ! areTodosReady || ! merchantIsReady ) {
return ;
}
diff --git a/modules/ppcp-settings/resources/js/data/_example/hooks.js b/modules/ppcp-settings/resources/js/data/_example/hooks.js
index 9df5d43d3..4c88523b5 100644
--- a/modules/ppcp-settings/resources/js/data/_example/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/_example/hooks.js
@@ -38,10 +38,15 @@ const useStoreData = () => {
};
export const useStore = () => {
- const { dispatch, useTransient } = useStoreData();
+ const { select, dispatch, useTransient } = useStoreData();
const { persist, refresh } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
+ // Load persistent data from REST if not done yet.
+ if ( ! isReady ) {
+ select.persistentData();
+ }
+
return { persist, refresh, isReady };
};
diff --git a/modules/ppcp-settings/resources/js/data/common/hooks.js b/modules/ppcp-settings/resources/js/data/common/hooks.js
index 49e5736a1..fd6ba3157 100644
--- a/modules/ppcp-settings/resources/js/data/common/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/common/hooks.js
@@ -96,10 +96,15 @@ const useHooks = () => {
};
export const useStore = () => {
- const { dispatch, useTransient } = useStoreData();
+ const { select, dispatch, useTransient } = useStoreData();
const { persist, refresh } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
+ // Load persistent data from REST if not done yet.
+ if ( ! isReady ) {
+ select.persistentData();
+ }
+
return { persist, refresh, isReady };
};
diff --git a/modules/ppcp-settings/resources/js/data/payment/hooks.js b/modules/ppcp-settings/resources/js/data/payment/hooks.js
index 582fd86f6..6060041f4 100644
--- a/modules/ppcp-settings/resources/js/data/payment/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/payment/hooks.js
@@ -38,10 +38,15 @@ const useStoreData = () => {
};
export const useStore = () => {
- const { useTransient, dispatch } = useStoreData();
+ const { select, useTransient, dispatch } = useStoreData();
const { persist, refresh, setPersistent, changePaymentSettings } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
+ // Load persistent data from REST if not done yet.
+ if ( ! isReady ) {
+ select.persistentData();
+ }
+
return {
persist,
refresh,
diff --git a/modules/ppcp-settings/resources/js/data/settings/hooks.js b/modules/ppcp-settings/resources/js/data/settings/hooks.js
index a79f1fc6d..4a97afa9e 100644
--- a/modules/ppcp-settings/resources/js/data/settings/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/settings/hooks.js
@@ -98,10 +98,15 @@ const useHooks = () => {
};
export const useStore = () => {
- const { dispatch, useTransient } = useStoreData();
+ const { select, dispatch, useTransient } = useStoreData();
const { persist, refresh } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
+ // Load persistent data from REST if not done yet.
+ if ( ! isReady ) {
+ select.persistentData();
+ }
+
return { persist, refresh, isReady };
};
diff --git a/modules/ppcp-settings/resources/js/data/styling/hooks.js b/modules/ppcp-settings/resources/js/data/styling/hooks.js
index a9d7bcbd6..ecf999eaf 100644
--- a/modules/ppcp-settings/resources/js/data/styling/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/styling/hooks.js
@@ -20,6 +20,7 @@ import {
STYLING_PAYMENT_METHODS,
STYLING_SHAPES,
} from './configuration';
+import { persistentData } from './selectors';
/**
* Single source of truth for access Redux details.
@@ -92,10 +93,15 @@ const useHooks = () => {
};
export const useStore = () => {
- const { dispatch, useTransient } = useStoreData();
+ const { select, dispatch, useTransient } = useStoreData();
const { persist, refresh } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
+ // Load persistent data from REST if not done yet.
+ if ( ! isReady ) {
+ select.persistentData();
+ }
+
return { persist, refresh, isReady };
};
diff --git a/modules/ppcp-settings/resources/js/data/todos/hooks.js b/modules/ppcp-settings/resources/js/data/todos/hooks.js
index f7bae751b..5ce97a636 100644
--- a/modules/ppcp-settings/resources/js/data/todos/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/todos/hooks.js
@@ -81,10 +81,15 @@ const useHooks = () => {
};
export const useStore = () => {
- const { dispatch, useTransient } = useStoreData();
+ const { select, dispatch, useTransient } = useStoreData();
const { persist, refresh } = dispatch;
const [ isReady ] = useTransient( 'isReady' );
+ // Load persistent data from REST if not done yet.
+ if ( ! isReady ) {
+ select.getTodos();
+ }
+
return { persist, refresh, isReady };
};