From dc77a0929358e2e63dcd7f460c9bb53442045667 Mon Sep 17 00:00:00 2001 From: frosso Date: Tue, 15 Jul 2025 14:16:56 +0200 Subject: [PATCH 1/5] fix: MCCY settings confirmation dialog --- changelog/fix-multi-currency-unload-confirmation-dialog | 4 ++++ includes/multi-currency/Settings.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog/fix-multi-currency-unload-confirmation-dialog diff --git a/changelog/fix-multi-currency-unload-confirmation-dialog b/changelog/fix-multi-currency-unload-confirmation-dialog new file mode 100644 index 00000000000..2508369174e --- /dev/null +++ b/changelog/fix-multi-currency-unload-confirmation-dialog @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +fix: ensure the confirmation dialog doesn't show up on the multi-currency UI diff --git a/includes/multi-currency/Settings.php b/includes/multi-currency/Settings.php index 8fe0a4aafcd..ea96ed42924 100644 --- a/includes/multi-currency/Settings.php +++ b/includes/multi-currency/Settings.php @@ -80,7 +80,7 @@ public function wcpay_multi_currency_settings_page() { // Hide original save button. $GLOBALS['hide_save_button'] = true; ?> -
+
Date: Tue, 15 Jul 2025 14:58:01 +0200 Subject: [PATCH 2/5] adding a custom confirmation --- includes/multi-currency/client/index.js | 38 ++++++++++- .../multi-currency/store-settings/index.js | 8 ++- .../client/settings/single-currency/index.js | 63 ++++++++++++------- 3 files changed, 81 insertions(+), 28 deletions(-) diff --git a/includes/multi-currency/client/index.js b/includes/multi-currency/client/index.js index 106fd4edf7c..ac595efbdf0 100644 --- a/includes/multi-currency/client/index.js +++ b/includes/multi-currency/client/index.js @@ -1,8 +1,9 @@ /** * External dependencies */ -import React, { useState } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import ReactDOM from 'react-dom'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -11,18 +12,51 @@ import MultiCurrencySettings from './settings/multi-currency'; import SingleCurrencySettings from './settings/single-currency'; import MultiCurrencySettingsContext from './context'; import UnbundledWpComponentsProvider from 'wcpay/wordpress-components-context/unbundled-wp-components-provider'; +import useConfirmNavigation from 'wcpay/utils/use-confirm-navigation'; const MultiCurrencySettingsPage = () => { const [ currencyCodeToShowSettingsFor, - setCurrencyCodeToShowSettingsFor, + _setCurrencyCodeToShowSettingsFor, ] = useState( null ); + const [ isCurrentScreenDirty, setIsCurrentScreenDirty ] = useState( false ); + useEffect( + useConfirmNavigation( () => { + if ( isCurrentScreenDirty ) { + return __( + 'There are unsaved changes on this page. Are you sure you want to leave and discard the unsaved changes?', + 'woocommerce-payments' + ); + } + } ), + [ isCurrentScreenDirty ] + ); + useEffect( () => { + setIsCurrentScreenDirty( false ); + }, [ currencyCodeToShowSettingsFor ] ); + const setCurrencyCodeToShowSettingsFor = useCallback( + ( currency ) => { + if ( + confirm( + __( + 'There are unsaved changes on this page. Are you sure you want to leave and discard the unsaved changes?', + 'woocommerce-payments' + ) + ) + ) { + _setCurrencyCodeToShowSettingsFor( currency ); + } + }, + [ isCurrentScreenDirty ] + ); return ( { ! currencyCodeToShowSettingsFor ? ( diff --git a/includes/multi-currency/client/settings/multi-currency/store-settings/index.js b/includes/multi-currency/client/settings/multi-currency/store-settings/index.js index c8d5e248be7..9941edb6362 100644 --- a/includes/multi-currency/client/settings/multi-currency/store-settings/index.js +++ b/includes/multi-currency/client/settings/multi-currency/store-settings/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import React, { useEffect, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { Button } from 'wcpay/components/wp-components-wrapped/components/button'; import { Card } from 'wcpay/components/wp-components-wrapped/components/card'; import { CardBody } from 'wcpay/components/wp-components-wrapped/components/card-body'; @@ -19,6 +19,7 @@ import { SettingsSection, } from 'multi-currency/interface/components'; import PreviewModal from 'multi-currency/components/preview-modal'; +import MultiCurrencySettingsContext from 'multi-currency/context'; const StoreSettingsDescription = () => ( <> @@ -60,7 +61,10 @@ const StoreSettings = () => { const [ isPreviewModalOpen, setPreviewModalOpen ] = useState( false ); - const [ isDirty, setIsDirty ] = useState( false ); + const { + setIsCurrentScreenDirty: setIsDirty, + isCurrentScreenDirty: isDirty, + } = useContext( MultiCurrencySettingsContext ); useEffect( () => { if ( Object.keys( storeSettings ).length ) { diff --git a/includes/multi-currency/client/settings/single-currency/index.js b/includes/multi-currency/client/settings/single-currency/index.js index 0d6e5cb7766..ed80ee77391 100644 --- a/includes/multi-currency/client/settings/single-currency/index.js +++ b/includes/multi-currency/client/settings/single-currency/index.js @@ -2,7 +2,7 @@ /** * External dependencies */ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect, useState, useCallback } from 'react'; import { dateI18n } from '@wordpress/date'; import { sprintf, __ } from '@wordpress/i18n'; import moment from 'moment'; @@ -18,7 +18,6 @@ import { Card } from 'wcpay/components/wp-components-wrapped/components/card'; import { CardBody } from 'wcpay/components/wp-components-wrapped/components/card-body'; import { SelectControl } from 'wcpay/components/wp-components-wrapped/components/select-control'; import { TextControl } from 'wcpay/components/wp-components-wrapped/components/text-control'; -import clsx from 'clsx'; import { decimalCurrencyCharmOptions, decimalCurrencyRoundingOptions, @@ -39,6 +38,30 @@ import { } from 'multi-currency/interface/components'; import interpolateComponents from '@automattic/interpolate-components'; +const CurrencyPreviewDescription = ( { + storeCurrency, + targetCurrency, + isLoading, +} ) => ( + <> +

{ __( 'Preview', 'woocommerce-payments' ) }

+

+ { ! isLoading + ? sprintf( + __( + 'Enter a price in your default currency (%s) to ' + + 'see it converted to %s using the ' + + 'exchange rate and formatting rules above.', + 'woocommerce-payments' + ), + storeCurrency, + targetCurrency + ) + : '' } +

+ +); + const CurrencySettingsDescription = () => ( <>

{ __( 'Currency settings', 'woocommerce-payments' ) }

@@ -57,10 +80,10 @@ const SingleCurrencySettings = () => { const { currencyCodeToShowSettingsFor: currency, setCurrencyCodeToShowSettingsFor, + setIsCurrentScreenDirty: setIsDirty, + isCurrentScreenDirty: isDirty, } = useContext( MultiCurrencySettingsContext ); - const [ isDirty, setIsDirty ] = useState( false ); - const { currencies } = useCurrencies(); const { enabledCurrencies } = useEnabledCurrencies(); const { storeSettings } = useStoreSettings(); @@ -132,25 +155,6 @@ const SingleCurrencySettings = () => { moment.unix( targetCurrency.last_updated ).toISOString() ) : ''; - const CurrencyPreviewDescription = () => ( - <> -

{ __( 'Preview', 'woocommerce-payments' ) }

-

- { ! isLoading - ? sprintf( - __( - 'Enter a price in your default currency (%s) to ' + - 'see it converted to %s using the ' + - 'exchange rate and formatting rules above.', - 'woocommerce-payments' - ), - storeCurrency.name, - targetCurrency.name - ) - : '' } -

- - ); const saveSingleCurrencySettings = () => { setIsSaving( true ); @@ -172,6 +176,17 @@ const SingleCurrencySettings = () => { setIsDirty( false ); }; + const currencyPreviewDescription = useCallback( + () => ( + + ), + [ storeCurrency.name, targetCurrency.name, isLoading ] + ); + return (
@@ -410,7 +425,7 @@ const SingleCurrencySettings = () => { - + Date: Tue, 15 Jul 2025 16:11:58 +0200 Subject: [PATCH 3/5] WIP --- .../__snapshots__/index.test.js.snap | 259 ------------------ 1 file changed, 259 deletions(-) delete mode 100644 includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap diff --git a/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap b/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap deleted file mode 100644 index 8071210d302..00000000000 --- a/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap +++ /dev/null @@ -1,259 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Multi-Currency store settings store settings task renders correctly: snapshot-multi-currency-store_settings 1`] = ` -.emotion-2 { - width: 1em; - height: 1em; - margin: 0; - vertical-align: middle; - fill: currentColor; -} - -.emotion-4 { - background-color: #fff; - color: #1e1e1e; - position: relative; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); - outline: none; - border-radius: calc(2px - 1px); -} - -.emotion-6 { - height: 100%; -} - -.emotion-8 { - box-sizing: border-box; - height: auto; - max-height: 100%; - padding: calc(4px * 4) calc(4px * 6); -} - -.emotion-8:first-of-type { - border-top-left-radius: calc(2px - 1px); - border-top-right-radius: calc(2px - 1px); -} - -.emotion-8:last-of-type { - border-bottom-left-radius: calc(2px - 1px); - border-bottom-right-radius: calc(2px - 1px); -} - -.emotion-10 { - font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif; - font-size: 13px; -} - -.emotion-12 { - margin-bottom: calc(4px * 2); -} - -.components-panel__row .emotion-12 { - margin-bottom: inherit; -} - -.emotion-14 { - margin-top: calc(4px * 2); - margin-bottom: 0; - font-size: 12px; - font-style: normal; - color: #757575; - margin-bottom: revert; -} - -.emotion-22 { - background: transparent; - display: block; - margin: 0!important; - pointer-events: none; - position: absolute; - will-change: box-shadow; - border-radius: inherit; - bottom: 0; - box-shadow: 0 0px 0px 0 rgba(0 ,0, 0, 0); - opacity: 1; - left: 0; - right: 0; - top: 0; - -webkit-transition: box-shadow 200ms cubic-bezier(0.08, 0.52, 0.52, 1); - transition: box-shadow 200ms cubic-bezier(0.08, 0.52, 0.52, 1); - border-radius: 2px; -} - -@media ( prefers-reduced-motion: reduce ) { - .emotion-22 { - transition-duration: 0ms; - } -} - -
-
-
-

- Store settings -

-

- Store settings allow your customers to choose which currency they would like to use when shopping at your store. - - Learn more - - (opens in a new tab) - - - -

-
-
-
-
-
-
-
- - - - -
-

- Customers will be notified via store alert banner. - -

-
-
-
- - - - -
-

- A currency switcher is also available in your widgets. - - Configure now - -

-
-
-
- -
-
-
-
- -
-
-
-`; From a98013dea7360bd9c8099fbfdf802afd8e7b01cd Mon Sep 17 00:00:00 2001 From: frosso Date: Tue, 15 Jul 2025 17:44:12 +0200 Subject: [PATCH 4/5] WIP --- .../__snapshots__/index.test.js.snap | 259 ++++++++++++++++++ .../store-settings/__tests__/index.test.js | 11 +- .../single-currency/__tests__/index.test.js | 2 + .../__tests__/index.test.js | 10 +- 4 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap diff --git a/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap b/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap new file mode 100644 index 00000000000..8071210d302 --- /dev/null +++ b/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/__snapshots__/index.test.js.snap @@ -0,0 +1,259 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Multi-Currency store settings store settings task renders correctly: snapshot-multi-currency-store_settings 1`] = ` +.emotion-2 { + width: 1em; + height: 1em; + margin: 0; + vertical-align: middle; + fill: currentColor; +} + +.emotion-4 { + background-color: #fff; + color: #1e1e1e; + position: relative; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); + outline: none; + border-radius: calc(2px - 1px); +} + +.emotion-6 { + height: 100%; +} + +.emotion-8 { + box-sizing: border-box; + height: auto; + max-height: 100%; + padding: calc(4px * 4) calc(4px * 6); +} + +.emotion-8:first-of-type { + border-top-left-radius: calc(2px - 1px); + border-top-right-radius: calc(2px - 1px); +} + +.emotion-8:last-of-type { + border-bottom-left-radius: calc(2px - 1px); + border-bottom-right-radius: calc(2px - 1px); +} + +.emotion-10 { + font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif; + font-size: 13px; +} + +.emotion-12 { + margin-bottom: calc(4px * 2); +} + +.components-panel__row .emotion-12 { + margin-bottom: inherit; +} + +.emotion-14 { + margin-top: calc(4px * 2); + margin-bottom: 0; + font-size: 12px; + font-style: normal; + color: #757575; + margin-bottom: revert; +} + +.emotion-22 { + background: transparent; + display: block; + margin: 0!important; + pointer-events: none; + position: absolute; + will-change: box-shadow; + border-radius: inherit; + bottom: 0; + box-shadow: 0 0px 0px 0 rgba(0 ,0, 0, 0); + opacity: 1; + left: 0; + right: 0; + top: 0; + -webkit-transition: box-shadow 200ms cubic-bezier(0.08, 0.52, 0.52, 1); + transition: box-shadow 200ms cubic-bezier(0.08, 0.52, 0.52, 1); + border-radius: 2px; +} + +@media ( prefers-reduced-motion: reduce ) { + .emotion-22 { + transition-duration: 0ms; + } +} + +
+
+
+

+ Store settings +

+

+ Store settings allow your customers to choose which currency they would like to use when shopping at your store. + + Learn more + + (opens in a new tab) + + + +

+
+
+
+
+
+
+
+ + + + +
+

+ Customers will be notified via store alert banner. + +

+
+
+
+ + + + +
+

+ A currency switcher is also available in your widgets. + + Configure now + +

+
+
+
+ +
+
+
+
+ +
+
+
+`; diff --git a/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/index.test.js b/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/index.test.js index 0aadcd7720d..df85e306e85 100644 --- a/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/index.test.js +++ b/includes/multi-currency/client/settings/multi-currency/store-settings/__tests__/index.test.js @@ -9,6 +9,7 @@ import { render, screen, fireEvent } from '@testing-library/react'; */ import { useStoreSettings } from 'multi-currency/data'; import StoreSettings from '..'; +import MultiCurrencySettingsContext from 'multi-currency/context'; jest.mock( 'multi-currency/data', () => ( { useStoreSettings: jest.fn(), @@ -29,7 +30,13 @@ useStoreSettings.mockReturnValue( { } ); const createContainer = () => { - const { container } = render( ); + const { container } = render( + null } } + > + + + ); return container; }; @@ -60,7 +67,7 @@ describe( 'Multi-Currency store settings', () => { } ); } ); - test( 'store settings button is diabled by default', () => { + test( 'store settings button is disabled by default', () => { createContainer(); expect( screen.getByRole( 'button', { name: /Save changes/ } ) diff --git a/includes/multi-currency/client/settings/single-currency/__tests__/index.test.js b/includes/multi-currency/client/settings/single-currency/__tests__/index.test.js index 116121e53a3..9a37299280b 100644 --- a/includes/multi-currency/client/settings/single-currency/__tests__/index.test.js +++ b/includes/multi-currency/client/settings/single-currency/__tests__/index.test.js @@ -129,6 +129,8 @@ useStoreSettings.mockReturnValue( { const containerContext = { currencyCodeToShowSettingsFor: 'EUR', setCurrencyCodeToShowSettingsFor: jest.fn(), + isCurrentScreenDirty: false, + setIsCurrentScreenDirty: jest.fn(), }; const getContainer = () => { diff --git a/includes/multi-currency/client/setup/tasks/store-settings-task/__tests__/index.test.js b/includes/multi-currency/client/setup/tasks/store-settings-task/__tests__/index.test.js index d80e8f8d12a..4a11f2b0692 100644 --- a/includes/multi-currency/client/setup/tasks/store-settings-task/__tests__/index.test.js +++ b/includes/multi-currency/client/setup/tasks/store-settings-task/__tests__/index.test.js @@ -11,6 +11,7 @@ import { useCurrencies, useStoreSettings } from 'multi-currency/data'; import { useSettings, useMultiCurrency } from 'multi-currency/interface/data'; import { WizardTaskContext } from 'multi-currency/interface/functions'; import StoreSettingsTask from '..'; +import MultiCurrencySettingsContext from 'multi-currency/context'; jest.mock( 'multi-currency/data', () => ( { useStoreSettings: jest.fn(), @@ -62,7 +63,14 @@ const createContainer = () => { - + null, + isCurrentScreenDirty: true, + } } + > + + ); return container; From 690d6ed3556dfa2e876dffb388cb12335832099a Mon Sep 17 00:00:00 2001 From: frosso Date: Tue, 15 Jul 2025 17:52:45 +0200 Subject: [PATCH 5/5] WIP --- .../single-currency/__tests__/__snapshots__/index.test.js.snap | 1 - .../client/settings/single-currency/__tests__/index.test.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/includes/multi-currency/client/settings/single-currency/__tests__/__snapshots__/index.test.js.snap b/includes/multi-currency/client/settings/single-currency/__tests__/__snapshots__/index.test.js.snap index c3e205b4132..34131fb8a6d 100644 --- a/includes/multi-currency/client/settings/single-currency/__tests__/__snapshots__/index.test.js.snap +++ b/includes/multi-currency/client/settings/single-currency/__tests__/__snapshots__/index.test.js.snap @@ -783,7 +783,6 @@ exports[`Single currency settings screen Page renders correctly 1`] = ` >