Commit f3ac26246c for woocommerce
commit f3ac26246c85635bd688baa13a420d3562cebd1b
Author: Ahmed <ahmed.el.azzabi@automattic.com>
Date: Tue Jul 1 10:38:49 2025 +0200
Improve offline payments settings navigation to avoid unnecessary refresh (#59163)
* Update settings URL for offline payment methods
* Add removeOriginFromURL function to help with navigation
* For offline payment methods, navigate to the URL instead of using href
* Navigate instead of changing location href
* Update the offline placeholder to include a header to avoid sudden changes in the UI
* Update links to the new format
* Update BACS component to use a header
* Add a header to the offline payment methods page
* Add a header to the BACS PM
* Add necessary header styles
* Remove unnecessary margin forcing
* Add cheque payments header
* Add COD header
* Add header to the loading state to avoid sudden UI changes
* Move SettingsPaymentsMainWrapper to after components definitions and declare new routes
* reduce code duplication by removing the header out of suspense and the component
* reduce code duplication by removing the header out of suspense and the component
* reduce code duplication by moving the header out for COD
* reduce duplication by moving the header out of the cheque component
* Fix typo in check payments
* Fix styling issues by wrapping the components in a div
* Update comment
* add redirection for old paths
* First try to fix lint issues
* Add a comma after the last argument
* Fix tests after changing the URLs
* Add changefile(s) from automation for the following project(s): @woocommerce/data, woocommerce, woocommerce/client/admin
* Default to url if we can not run a replace
* reduce code duplication by using a central component
* Remove the Header as it's not used anymore
* Fix components layouts
* Wrap SettingsPaymentsMain test file in Router
* Add margins for offline settings
* Remove non used Take offline payments header
* remove unit from CSS
* remove border bottom from header layout
* add margins for offline container to match the settings container
* Get back to the checkout tab in settings in order to remove the path query arg
* clear store when navigating back to offline PMs list
* Add get_settings_url for cod, cheque, and bacs
---------
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
Co-authored-by: Vlad Olaru <vlad.olaru@automattic.com>
diff --git a/packages/js/data/changelog/59163-update-update-offline-pms-navigation b/packages/js/data/changelog/59163-update-update-offline-pms-navigation
new file mode 100644
index 0000000000..eda5f06e45
--- /dev/null
+++ b/packages/js/data/changelog/59163-update-update-offline-pms-navigation
@@ -0,0 +1,4 @@
+Significance: minor
+Type: update
+
+Update the navigation for offline payment methods to avoid unnecessary page refresh
\ No newline at end of file
diff --git a/packages/js/data/src/payment-settings/test/helpers/stub.ts b/packages/js/data/src/payment-settings/test/helpers/stub.ts
index 2edad8823a..923afaaab7 100644
--- a/packages/js/data/src/payment-settings/test/helpers/stub.ts
+++ b/packages/js/data/src/payment-settings/test/helpers/stub.ts
@@ -183,7 +183,7 @@ export const offlinePaymentGatewaysStub: OfflinePaymentMethodProvider[] = [
management: {
_links: {
settings: {
- href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=bacs',
+ href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/bacs',
},
},
},
@@ -195,7 +195,7 @@ export const offlinePaymentGatewaysStub: OfflinePaymentMethodProvider[] = [
},
_links: {
onboard: {
- href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=bacs',
+ href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/bacs',
},
},
},
@@ -226,7 +226,7 @@ export const offlinePaymentGatewaysStub: OfflinePaymentMethodProvider[] = [
management: {
_links: {
settings: {
- href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cheque',
+ href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cheque',
},
},
},
@@ -238,7 +238,7 @@ export const offlinePaymentGatewaysStub: OfflinePaymentMethodProvider[] = [
},
_links: {
onboard: {
- href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cheque',
+ href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cheque',
},
},
},
@@ -269,7 +269,7 @@ export const offlinePaymentGatewaysStub: OfflinePaymentMethodProvider[] = [
management: {
_links: {
settings: {
- href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cod',
+ href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cod',
},
},
},
@@ -281,7 +281,7 @@ export const offlinePaymentGatewaysStub: OfflinePaymentMethodProvider[] = [
},
_links: {
onboard: {
- href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cod',
+ href: 'http://localhost:8082/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cod',
},
},
},
diff --git a/plugins/woocommerce/changelog/59163-update-update-offline-pms-navigation b/plugins/woocommerce/changelog/59163-update-update-offline-pms-navigation
new file mode 100644
index 0000000000..eda5f06e45
--- /dev/null
+++ b/plugins/woocommerce/changelog/59163-update-update-offline-pms-navigation
@@ -0,0 +1,4 @@
+Significance: minor
+Type: update
+
+Update the navigation for offline payment methods to avoid unnecessary page refresh
\ No newline at end of file
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/settings-button.tsx b/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/settings-button.tsx
index 12eccf614a..081df9e1a6 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/settings-button.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/settings-button.tsx
@@ -6,12 +6,17 @@ import { Button } from '@wordpress/components';
import {
OfflinePaymentMethodProvider,
PaymentGatewayProvider,
+ PaymentsProviderType,
} from '@woocommerce/data';
+import { useNavigate } from 'react-router-dom';
/**
* Internal dependencies
*/
-import { recordPaymentsProviderEvent } from '~/settings-payments/utils';
+import {
+ recordPaymentsProviderEvent,
+ removeOriginFromURL,
+} from '~/settings-payments/utils';
interface SettingsButtonProps {
/**
@@ -43,6 +48,8 @@ export const SettingsButton = ( {
isInstallingPlugin,
buttonText = __( 'Manage', 'woocommerce' ),
}: SettingsButtonProps ) => {
+ const isOffline = gatewayProvider._type === PaymentsProviderType.OfflinePm;
+ const navigate = useNavigate();
const recordButtonClickEvent = () => {
recordPaymentsProviderEvent( 'provider_manage_click', gatewayProvider );
};
@@ -50,9 +57,14 @@ export const SettingsButton = ( {
return (
<Button
variant={ 'secondary' }
- href={ settingsHref }
+ href={ ! isOffline ? settingsHref : undefined }
disabled={ isInstallingPlugin }
- onClick={ recordButtonClickEvent }
+ onClick={ () => {
+ recordButtonClickEvent();
+ if ( isOffline ) {
+ navigate( removeOriginFromURL( settingsHref ) );
+ }
+ } }
>
{ buttonText }
</Button>
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/test/settings-button.test.tsx b/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/test/settings-button.test.tsx
index 0a05e081c9..4a0c8f80ac 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/test/settings-button.test.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/components/buttons/test/settings-button.test.tsx
@@ -3,6 +3,7 @@
*/
import { recordEvent } from '@woocommerce/tracks';
import { render, fireEvent } from '@testing-library/react';
+import { MemoryRouter as Router } from 'react-router-dom';
import {
PaymentGatewayProvider,
PaymentsProviderState,
@@ -22,35 +23,37 @@ jest.mock( '@woocommerce/tracks', () => ( {
describe( 'SettingsButton', () => {
it( 'should record settings_payments_provider_manage_click event on click of the button', () => {
const { getByRole } = render(
- <SettingsButton
- gatewayProvider={
- {
- id: 'test-gateway',
- state: {
- enabled: true,
- account_connected: false,
- needs_setup: true,
- test_mode: false,
- dev_mode: false,
- } as PaymentsProviderState,
- onboarding: {
+ <Router>
+ <SettingsButton
+ gatewayProvider={
+ {
+ id: 'test-gateway',
state: {
- started: true,
- completed: false,
+ enabled: true,
+ account_connected: false,
+ needs_setup: true,
test_mode: false,
- } as PaymentsProviderOnboardingState,
- },
- plugin: {
- slug: 'test-plugin',
- file: 'test-file',
- status: 'installed',
- } as PluginData,
- _suggestion_id: 'test-suggestion',
- _type: 'gateway',
- } as PaymentGatewayProvider
- }
- settingsHref={ '' }
- />
+ dev_mode: false,
+ } as PaymentsProviderState,
+ onboarding: {
+ state: {
+ started: true,
+ completed: false,
+ test_mode: false,
+ } as PaymentsProviderOnboardingState,
+ },
+ plugin: {
+ slug: 'test-plugin',
+ file: 'test-file',
+ status: 'installed',
+ } as PluginData,
+ _suggestion_id: 'test-suggestion',
+ _type: 'gateway',
+ } as PaymentGatewayProvider
+ }
+ settingsHref={ '' }
+ />
+ </Router>
);
fireEvent.click( getByRole( 'link', { name: 'Manage' } ) );
expect( recordEvent ).toHaveBeenCalledWith(
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list/payment-gateway-list.tsx b/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list/payment-gateway-list.tsx
index 6035290e52..ca55237abe 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list/payment-gateway-list.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list/payment-gateway-list.tsx
@@ -10,6 +10,7 @@ import {
PaymentsExtensionSuggestionProvider,
} from '@woocommerce/data';
import { Gridicon } from '@automattic/components';
+import { useNavigate } from 'react-router-dom';
/**
* Internal dependencies
@@ -22,6 +23,7 @@ import {
import { PaymentExtensionSuggestionListItem } from '~/settings-payments/components/payment-extension-suggestion-list-item';
import { PaymentGatewayListItem } from '~/settings-payments/components/payment-gateway-list-item';
import './payment-gateway-list.scss';
+import { removeOriginFromURL } from '~/settings-payments/utils';
interface PaymentGatewayListProps {
/**
@@ -86,6 +88,8 @@ export const PaymentGatewayList = ( {
updateOrdering,
setIsOnboardingModalOpen,
}: PaymentGatewayListProps ) => {
+ const navigate = useNavigate();
+
return (
<SortableContainer< PaymentsProvider >
items={ providers }
@@ -146,8 +150,12 @@ export const PaymentGatewayList = ( {
id={ offlinePmsGroup.id }
className="transitions-disabled woocommerce-list__item clickable-list-item enter-done"
onClick={ () => {
- window.location.href =
- offlinePmsGroup.management._links.settings.href;
+ navigate(
+ removeOriginFromURL(
+ offlinePmsGroup.management
+ ._links.settings.href
+ )
+ );
} }
>
<div className="woocommerce-list__item-inner">
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/components/settings/settings.scss b/plugins/woocommerce/client/admin/client/settings-payments/components/settings/settings.scss
index 441b01c41a..0cc5bcde44 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/components/settings/settings.scss
+++ b/plugins/woocommerce/client/admin/client/settings-payments/components/settings/settings.scss
@@ -1,7 +1,3 @@
-.woocommerce-layout__header {
- border-bottom: 1px solid $gray-200;
-}
-
.settings-layout {
margin: 48px 12px 0;
display: flex;
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/index.tsx b/plugins/woocommerce/client/admin/client/settings-payments/index.tsx
index 17eb13df97..ada17ae876 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/index.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/index.tsx
@@ -4,7 +4,7 @@
import { Gridicon } from '@automattic/components';
import { Button, Placeholder, SelectControl } from '@wordpress/components';
import { paymentSettingsStore } from '@woocommerce/data';
-import { useSelect } from '@wordpress/data';
+import { useSelect, useDispatch } from '@wordpress/data';
import React, {
useState,
lazy,
@@ -20,7 +20,6 @@ import {
} from 'react-router-dom';
import { getHistory, getNewPath } from '@woocommerce/navigation';
import { __ } from '@wordpress/i18n';
-import { getAdminLink } from '@woocommerce/settings';
import { recordEvent } from '@woocommerce/tracks';
/**
@@ -96,6 +95,70 @@ const SettingsPaymentsChequeChunk = lazy(
)
);
+interface OfflinePaymentGatewayWrapperProps {
+ title: string;
+ chunkComponent: React.ComponentType;
+}
+
+const OfflinePaymentGatewayWrapper = ( {
+ title,
+ chunkComponent: ChunkComponent,
+}: OfflinePaymentGatewayWrapperProps ) => {
+ const { invalidateResolution, invalidateResolutionForStoreSelector } =
+ useDispatch( paymentSettingsStore );
+
+ return (
+ <>
+ <div className="settings-payments-offline__container">
+ <div className="settings-payment-gateways">
+ <div className="settings-payments-offline__header">
+ <div
+ onClick={ () => {
+ // Invalidate the payment providers and offline payment gateways stores.
+ // This is to ensure that the data is refreshed when the user navigates back to the offline payment settings page.
+ invalidateResolution(
+ 'getPaymentProviders',
+ []
+ );
+ invalidateResolutionForStoreSelector(
+ 'getOfflinePaymentGateways'
+ );
+ } }
+ role="button"
+ tabIndex={ 0 }
+ onKeyDown={ ( e ) => {
+ if ( e.key === 'Enter' ) {
+ invalidateResolutionForStoreSelector(
+ 'getOfflinePaymentGateways'
+ );
+ }
+ } }
+ >
+ <BackButton
+ href={ getNewPath( {}, '/offline' ) }
+ title={ __(
+ 'Return to payments settings',
+ 'woocommerce'
+ ) }
+ isRoute={ true }
+ from={ 'woopayments_payment_methods' }
+ />
+ </div>
+ <h1 className="components-truncate components-text woocommerce-layout__header-heading woocommerce-layout__header-left-align settings-payments-offline__header-title">
+ <span className="woocommerce-settings-payments-header__title">
+ { title }
+ </span>
+ </h1>
+ </div>
+ <Suspense fallback={ <Placeholder /> }>
+ <ChunkComponent />
+ </Suspense>
+ </div>
+ </div>
+ </>
+ );
+};
+
/**
* Hides or displays the WooCommerce navigation tab based on the provided display style.
*/
@@ -313,63 +376,37 @@ export const SettingsPaymentsMethods = () => {
);
};
-/**
- * Wraps the main payment settings and payment methods settings pages.
- */
-export const SettingsPaymentsMainWrapper = () => {
- return (
- <>
- <Header
- title={ __( 'Settings', 'woocommerce' ) }
- context={ 'wc_settings_payments__main' }
- />
- <HistoryRouter history={ getHistory() }>
- <Routes>
- <Route
- path="/payment-methods"
- element={ <SettingsPaymentsMethods /> }
- />
- <Route path="/*" element={ <SettingsPaymentsMain /> } />
- </Routes>
- </HistoryRouter>
- </>
- );
-};
-
/**
* Wraps the offline payment gateways settings page.
*/
export const SettingsPaymentsOfflineWrapper = () => {
return (
<>
- <Header
- title={ __( 'Take offline payments', 'woocommerce' ) }
- backLink={ getAdminLink(
- 'admin.php?page=wc-settings&tab=checkout'
- ) }
- context={ 'wc_settings_payments__offline_pms' }
- />
- <Suspense
- fallback={
- <>
- <div className="settings-payments-offline__container">
- <div className="settings-payment-gateways">
- <div className="settings-payment-gateways__header">
- <div className="settings-payment-gateways__header-title">
- { __(
- 'Payment methods',
- 'woocommerce'
- ) }
- </div>
- </div>
- <ListPlaceholder rows={ 3 } />
- </div>
- </div>
- </>
- }
- >
- <SettingsPaymentsOfflineChunk />
- </Suspense>
+ <div className="settings-payments-offline__container">
+ <div className="settings-payments-offline__header">
+ <BackButton
+ href={ getNewPath(
+ { page: 'wc-settings', tab: 'checkout' },
+ '/',
+ {}
+ ) }
+ title={ __(
+ 'Return to payments settings',
+ 'woocommerce'
+ ) }
+ isRoute={ true }
+ from={ 'woopayments_payment_methods' }
+ />
+ <h1 className="components-truncate components-text woocommerce-layout__header-heading woocommerce-layout__header-left-align">
+ <span className="woocommerce-settings-payments-header__title">
+ { __( 'Take offline payments', 'woocommerce' ) }
+ </span>
+ </h1>
+ </div>
+ <Suspense fallback={ <ListPlaceholder rows={ 3 } /> }>
+ <SettingsPaymentsOfflineChunk />
+ </Suspense>
+ </div>
</>
);
};
@@ -391,107 +428,59 @@ export const SettingsPaymentsWooPaymentsWrapper = () => {
);
};
-export const SettingsPaymentsBacsWrapper = () => {
- return (
- <>
- <Header
- title={ __( 'Direct bank transfer', 'woocommerce' ) }
- backLink={ getAdminLink(
- 'admin.php?page=wc-settings&tab=checkout§ion=offline'
- ) }
- context={ 'wc_settings_payments__offline_pms_bacs' }
- />
- <Suspense
- fallback={
- <>
- <div className="settings-payments-bacs__container">
- <div className="settings-payment-gateways">
- <div className="settings-payment-gateways__header">
- <div className="settings-payment-gateways__header-title">
- { __(
- 'Direct bank transfer',
- 'woocommerce'
- ) }
- </div>
- </div>
- <Placeholder />
- </div>
- </div>
- </>
- }
- >
- <SettingsPaymentsBacsChunk />
- </Suspense>
- </>
- );
-};
+export const SettingsPaymentsBacsWrapper = () =>
+ OfflinePaymentGatewayWrapper( {
+ title: __( 'Direct bank transfer', 'woocommerce' ),
+ chunkComponent: SettingsPaymentsBacsChunk,
+ } );
-export const SettingsPaymentsCodWrapper = () => {
- return (
- <>
- <Header
- title={ __( 'Cash on delivery', 'woocommerce' ) }
- backLink={ getAdminLink(
- 'admin.php?page=wc-settings&tab=checkout§ion=offline'
- ) }
- context={ 'wc_settings_payments__offline_pms_cod' }
- />
- <Suspense
- fallback={
- <>
- <div className="settings-payments-cod__container">
- <div className="settings-payment-gateways">
- <div className="settings-payment-gateways__header">
- <div className="settings-payment-gateways__header-title">
- { __(
- 'Cash on delivery',
- 'woocommerce'
- ) }
- </div>
- </div>
- <Placeholder />
- </div>
- </div>
- </>
- }
- >
- <SettingsPaymentsCodChunk />
- </Suspense>
- </>
- );
-};
+export const SettingsPaymentsCodWrapper = () =>
+ OfflinePaymentGatewayWrapper( {
+ title: __( 'Cash on delivery', 'woocommerce' ),
+ chunkComponent: SettingsPaymentsCodChunk,
+ } );
-export const SettingsPaymentsChequeWrapper = () => {
+export const SettingsPaymentsChequeWrapper = () =>
+ OfflinePaymentGatewayWrapper( {
+ title: __( 'Check payments', 'woocommerce' ),
+ chunkComponent: SettingsPaymentsChequeChunk,
+ } );
+
+/**
+ * Wraps the main payment settings and payment methods settings pages.
+ */
+export const SettingsPaymentsMainWrapper = () => {
return (
<>
<Header
- title={ __( 'Check payments', 'woocommerce' ) }
- backLink={ getAdminLink(
- 'admin.php?page=wc-settings&tab=checkout§ion=offline'
- ) }
- context={ 'wc_settings_payments__offline_pms_cheque' }
+ title={ __( 'Settings', 'woocommerce' ) }
+ context={ 'wc_settings_payments__main' }
/>
- <Suspense
- fallback={
- <>
- <div className="settings-payments-cheque__container">
- <div className="settings-payment-gateways">
- <div className="settings-payment-gateways__header">
- <div className="settings-payment-gateways__header-title">
- { __(
- 'Check payments',
- 'woocommerce'
- ) }
- </div>
- </div>
- <Placeholder />
- </div>
- </div>
- </>
- }
- >
- <SettingsPaymentsChequeChunk />
- </Suspense>
+ <HistoryRouter history={ getHistory() }>
+ <Routes>
+ <Route
+ path="/payment-methods"
+ element={ <SettingsPaymentsMethods /> }
+ />
+ <Route
+ path="/offline"
+ element={ <SettingsPaymentsOfflineWrapper /> }
+ />
+ <Route
+ path="/offline/bacs"
+ element={ <SettingsPaymentsBacsWrapper /> }
+ />
+ <Route
+ path="/offline/cod"
+ element={ <SettingsPaymentsCodWrapper /> }
+ />
+ <Route
+ path="/offline/cheque"
+ element={ <SettingsPaymentsChequeWrapper /> }
+ />
+ <Route path="/*" element={ <SettingsPaymentsMain /> } />
+ </Routes>
+ </HistoryRouter>
</>
);
};
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/offline/settings-payments-bacs.tsx b/plugins/woocommerce/client/admin/client/settings-payments/offline/settings-payments-bacs.tsx
index 9beb3e9258..10159015bd 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/offline/settings-payments-bacs.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/offline/settings-payments-bacs.tsx
@@ -20,6 +20,7 @@ import { Settings } from '~/settings-payments/components/settings';
import { FieldPlaceholder } from '~/settings-payments/components/field-placeholder';
import { BankAccountsList } from '~/settings-payments/components/bank-accounts-list';
import { BankAccount } from '~/settings-payments/components/bank-accounts-list/types';
+
/**
* This page is used to manage the settings for the BACS (Direct bank transfer) payment gateway.
*/
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss
index 067fb19eae..44240eb942 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss
+++ b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-body.scss
@@ -9,12 +9,12 @@ body.woocommerce-settings-payments-tab {
#wpcontent {
background-color: #fff;
}
+}
- .woocommerce-layout .woocommerce-store-alerts {
- margin-top: $gap-large;
- }
+.settings-payments-offline__container {
+ margin: 0 -30px;
- #wpbody.has-settings-layout {
- margin-top: 60px !important;
+ .settings-layout {
+ margin: 0 48px 0;
}
}
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-main.scss b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-main.scss
index 355f2bd394..59dc93007e 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-main.scss
+++ b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-main.scss
@@ -492,3 +492,19 @@ body.woocommerce-settings-payments-tab {
width: 256px;
}
}
+
+.settings-payments-offline__container {
+ .settings-payments-offline__header {
+ display: flex;
+ padding: 8px 48px 24px;
+ align-items: center;
+
+ h1 {
+ padding-left: $gap-smaller * 2;
+ // This is the same as the Payments settings header.
+ // This is used to keep the UI consistent across when navigating to the offline payments settings page.
+ line-height: 38px;
+ color: #3c434a;
+ }
+ }
+}
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-offline.tsx b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-offline.tsx
index 6e3f9afc72..b0599c8793 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-offline.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/settings-payments-offline.tsx
@@ -66,7 +66,7 @@ export const SettingsPaymentsOffline = () => {
}
return (
- <div className="settings-payments-offline__container">
+ <>
{ isFetching ? (
<ListPlaceholder rows={ 3 } />
) : (
@@ -77,7 +77,7 @@ export const SettingsPaymentsOffline = () => {
setGateways={ handleOrderingUpdate }
/>
) }
- </div>
+ </>
);
};
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/test/settings-payments-main.test.tsx b/plugins/woocommerce/client/admin/client/settings-payments/test/settings-payments-main.test.tsx
index 31a5f62860..fdae6797e6 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/test/settings-payments-main.test.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/test/settings-payments-main.test.tsx
@@ -3,6 +3,7 @@
*/
import { recordEvent } from '@woocommerce/tracks';
import { render, fireEvent, screen } from '@testing-library/react';
+import { MemoryRouter as Router } from 'react-router-dom';
/**
* Internal dependencies
@@ -19,7 +20,11 @@ jest.mock( '~/utils/features', () => ( {
describe( 'SettingsPaymentsMain', () => {
it( 'should record settings_payments_pageview event on load', () => {
- render( <SettingsPaymentsMain /> );
+ render(
+ <Router>
+ <SettingsPaymentsMain />
+ </Router>
+ );
expect( recordEvent ).toHaveBeenCalledWith(
'settings_payments_pageview',
@@ -30,7 +35,11 @@ describe( 'SettingsPaymentsMain', () => {
} );
it( 'should trigger event recommendations_other_options when clicking the WooCommerce Marketplace link', () => {
- render( <SettingsPaymentsMain /> );
+ render(
+ <Router>
+ <SettingsPaymentsMain />
+ </Router>
+ );
fireEvent.click( screen.getByText( 'the WooCommerce Marketplace' ) );
@@ -56,7 +65,11 @@ describe( 'SettingsPaymentsMain', () => {
value: mockLocation,
} );
- render( <SettingsPaymentsMain /> );
+ render(
+ <Router>
+ <SettingsPaymentsMain />
+ </Router>
+ );
fireEvent.click( screen.getByText( 'the WooCommerce Marketplace' ) );
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/utils.ts b/plugins/woocommerce/client/admin/client/settings-payments/utils.ts
index df33eb6d6f..f1b601bdec 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/utils.ts
+++ b/plugins/woocommerce/client/admin/client/settings-payments/utils.ts
@@ -9,6 +9,7 @@ import {
import { getAdminLink } from '@woocommerce/settings';
import apiFetch from '@wordpress/api-fetch';
import { recordEvent } from '@woocommerce/tracks';
+import { parseAdminUrl } from '@woocommerce/navigation';
/**
* Internal dependencies
@@ -449,3 +450,20 @@ export const recordPaymentsOnboardingEvent = (
recordEvent( eventName, data );
};
+
+/**
+ * Strips the origin from a URL. This is used for front-end navigation using react-router-dom.
+ *
+ * @example
+ * ```
+ * removeOriginFromURL( 'https://example.com/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline' )
+ * // returns '/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline'
+ * ```
+ *
+ * @param url The URL to strip the origin from.
+ * @return The URL with the origin stripped.
+ */
+export const removeOriginFromURL = ( url: string ) => {
+ const parsedUrl = parseAdminUrl( url );
+ return parsedUrl.href?.replace( parsedUrl.origin, '' ) ?? url;
+};
diff --git a/plugins/woocommerce/includes/admin/class-wc-admin.php b/plugins/woocommerce/includes/admin/class-wc-admin.php
index b4148bded7..a78946838d 100644
--- a/plugins/woocommerce/includes/admin/class-wc-admin.php
+++ b/plugins/woocommerce/includes/admin/class-wc-admin.php
@@ -141,7 +141,9 @@ class WC_Admin {
}
/**
- * Handle redirects to setup/welcome page after install and updates.
+ * Handle redirects:
+ * 1. To setup/welcome page after install and updates.
+ * 2. To offline payment gateway(s) new settings page.
*
* The user must have access rights, and we must ignore the network/bulk plugin updaters.
*/
@@ -168,6 +170,37 @@ class WC_Admin {
exit;
}
+ // Check if we have a section parameter for offline payment gateways and redirect to the new path.
+ if ( ! empty( $_GET['section'] ) ) {
+ $section = wc_clean( wp_unslash( $_GET['section'] ) );
+
+ // Handle offline payment gateway(s) redirections.
+ if ( 'offline' === $section || WC_Gateway_BACS::ID === $section || WC_Gateway_COD::ID === $section || WC_Gateway_Cheque::ID === $section ) {
+ // Get current URL and remove source parameter.
+ $current_url = remove_query_arg( 'section' );
+
+ if ( 'offline' === $section ) {
+ $redirect_url = add_query_arg(
+ array(
+ 'path' => '/offline',
+ ),
+ $current_url,
+ );
+ } else {
+ $redirect_url = add_query_arg(
+ array(
+ 'path' => '/offline/' . strtolower( $section ),
+ ),
+ $current_url,
+ );
+ }
+
+ // Perform the redirect.
+ wp_safe_redirect( $redirect_url );
+ exit;
+ }
+ }
+
// phpcs:enable WordPress.Security.NonceVerification.Recommended
}
diff --git a/plugins/woocommerce/includes/gateways/bacs/class-wc-gateway-bacs.php b/plugins/woocommerce/includes/gateways/bacs/class-wc-gateway-bacs.php
index 3dc1503243..92382647f9 100644
--- a/plugins/woocommerce/includes/gateways/bacs/class-wc-gateway-bacs.php
+++ b/plugins/woocommerce/includes/gateways/bacs/class-wc-gateway-bacs.php
@@ -485,4 +485,13 @@ class WC_Gateway_BACS extends WC_Payment_Gateway {
return $this->locale;
}
+
+ /**
+ * Get the settings URL for the gateway.
+ *
+ * @return string
+ */
+ public function get_settings_url() {
+ return admin_url( 'admin.php?page=wc-settings&tab=checkout&path=/offline/bacs' );
+ }
}
diff --git a/plugins/woocommerce/includes/gateways/cheque/class-wc-gateway-cheque.php b/plugins/woocommerce/includes/gateways/cheque/class-wc-gateway-cheque.php
index 9e27ff4a45..099f19d26b 100644
--- a/plugins/woocommerce/includes/gateways/cheque/class-wc-gateway-cheque.php
+++ b/plugins/woocommerce/includes/gateways/cheque/class-wc-gateway-cheque.php
@@ -169,4 +169,13 @@ class WC_Gateway_Cheque extends WC_Payment_Gateway {
'redirect' => $this->get_return_url( $order ),
);
}
+
+ /**
+ * Get the settings URL for the gateway.
+ *
+ * @return string
+ */
+ public function get_settings_url() {
+ return admin_url( 'admin.php?page=wc-settings&tab=checkout&path=/offline/cheque' );
+ }
}
diff --git a/plugins/woocommerce/includes/gateways/cod/class-wc-gateway-cod.php b/plugins/woocommerce/includes/gateways/cod/class-wc-gateway-cod.php
index f7b7e8dd91..ee083988f9 100644
--- a/plugins/woocommerce/includes/gateways/cod/class-wc-gateway-cod.php
+++ b/plugins/woocommerce/includes/gateways/cod/class-wc-gateway-cod.php
@@ -367,4 +367,13 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL );
}
}
+
+ /**
+ * Get the settings URL for the gateway.
+ *
+ * @return string
+ */
+ public function get_settings_url() {
+ return admin_url( 'admin.php?page=wc-settings&tab=checkout&path=/offline/cod' );
+ }
}
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php b/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php
index 0c5abdbaea..33105594bf 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php
@@ -158,7 +158,7 @@ class Payments {
'management' => array(
'_links' => array(
'settings' => array(
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=offline' ),
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&path=/offline' ),
),
),
),
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders/PaymentGateway.php b/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders/PaymentGateway.php
index 46c59772d2..97bd9d6828 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders/PaymentGateway.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders/PaymentGateway.php
@@ -11,6 +11,9 @@ use Automattic\WooCommerce\Internal\Logging\SafeGlobalFunctionProxy;
use Throwable;
use WC_HTTPS;
use WC_Payment_Gateway;
+use WC_Gateway_BACS;
+use WC_Gateway_COD;
+use WC_Gateway_Cheque;
defined( 'ABSPATH' ) || exit;
@@ -542,6 +545,17 @@ class PaymentGateway {
);
}
+ // Special handling for offline payment gateways to use the front-end navigation.
+ if ( WC_Gateway_BACS::ID === $payment_gateway->id || WC_Gateway_COD::ID === $payment_gateway->id || WC_Gateway_Cheque::ID === $payment_gateway->id ) {
+ return Utils::wc_payments_settings_url(
+ null,
+ array(
+ 'path' => '/offline/' . strtolower( $payment_gateway->id ),
+ 'from' => Payments::FROM_PAYMENTS_SETTINGS,
+ )
+ );
+ }
+
return Utils::wc_payments_settings_url(
null,
array(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/payment-gateways.php b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/payment-gateways.php
index 592cd0c01b..f4b449542e 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/payment-gateways.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version2/payment-gateways.php
@@ -79,7 +79,7 @@ class Payment_Gateways_V2 extends WC_REST_Unit_Test_Case {
),
'needs_setup' => false,
'post_install_scripts' => array(),
- 'settings_url' => 'http://' . WP_TESTS_DOMAIN . '/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cheque',
+ 'settings_url' => 'http://' . WP_TESTS_DOMAIN . '/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cheque',
'connection_url' => '',
'setup_help_text' => '',
'required_settings_keys' => array(),
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/payment-gateways.php b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/payment-gateways.php
index c242261bed..ae1fc927f1 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/payment-gateways.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/rest-api/Tests/Version3/payment-gateways.php
@@ -82,7 +82,7 @@ class Payment_Gateways extends WC_REST_Unit_Test_Case {
),
'needs_setup' => false,
'post_install_scripts' => array(),
- 'settings_url' => 'http://' . WP_TESTS_DOMAIN . '/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cheque',
+ 'settings_url' => 'http://' . WP_TESTS_DOMAIN . '/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cheque',
'connection_url' => '',
'setup_help_text' => '',
'required_settings_keys' => array(),
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsRestControllerTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsRestControllerTest.php
index e3822d46de..75e3a57130 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsRestControllerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsRestControllerTest.php
@@ -983,7 +983,7 @@ class PaymentsRestControllerTest extends WC_REST_Unit_Test_Case {
'management' => array(
'_links' => array(
'settings' => array(
- 'href' => 'http://localhost:8888/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=bacs',
+ 'href' => 'http://localhost:8888/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/bacs',
),
),
),
@@ -1019,7 +1019,7 @@ class PaymentsRestControllerTest extends WC_REST_Unit_Test_Case {
'management' => array(
'_links' => array(
'settings' => array(
- 'href' => 'http://localhost:8888/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cheque',
+ 'href' => 'http://localhost:8888/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cheque',
),
),
),
@@ -1055,7 +1055,7 @@ class PaymentsRestControllerTest extends WC_REST_Unit_Test_Case {
'management' => array(
'_links' => array(
'settings' => array(
- 'href' => 'http://localhost:8888/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=cod',
+ 'href' => 'http://localhost:8888/wp-admin/admin.php?page=wc-settings&tab=checkout&path=/offline/cod',
),
),
),