From bf92f8942d4895e39ffc956e4ec357978f02a2c8 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 7 Sep 2023 09:13:57 +0100 Subject: [PATCH 1/3] Refactor ScriptLoading, removed timeout feature Refactor SmartButton render hooks --- .../js/modules/Helper/ScriptLoading.js | 11 +------- .../ppcp-button/src/Assets/SmartButton.php | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js b/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js index 84de36af6..fea81923b 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js +++ b/modules/ppcp-button/resources/js/modules/Helper/ScriptLoading.js @@ -7,8 +7,7 @@ import {keysToCamelCase} from "./Utils"; // This component may be used by multiple modules. This assures that options are shared between all instances. let options = window.ppcpWidgetBuilder = window.ppcpWidgetBuilder || { isLoading: false, - onLoadedCallbacks: [], - loadingWaitTime: 5000 // 5 seconds + onLoadedCallbacks: [] }; export const loadPaypalScript = (config, onLoaded) => { @@ -27,13 +26,6 @@ export const loadPaypalScript = (config, onLoaded) => { } options.isLoading = true; - // Arm a timeout so the module isn't locked on isLoading state on failure. - let loadingTimeout = setTimeout(() => { - console.error('Failed to load PayPal script.'); - options.isLoading = false; - options.onLoadedCallbacks = []; - }, options.loadingWaitTime); - // Callback to be called once the PayPal script is loaded. const callback = (paypal) => { widgetBuilder.setPaypal(paypal); @@ -44,7 +36,6 @@ export const loadPaypalScript = (config, onLoaded) => { options.isLoading = false; options.onLoadedCallbacks = []; - clearTimeout(loadingTimeout); } // Build the PayPal script options. diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 6fbe65b29..6d88e7ec6 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -462,8 +462,7 @@ class SmartButton implements SmartButtonInterface { return; } - $this->button_renderer( PayPalGateway::ID ); - do_action( 'woocommerce_paypal_payments_single_product_button_render' ); + $this->button_renderer( PayPalGateway::ID, 'woocommerce_paypal_payments_single_product_button_render' ); }, 31 ); @@ -495,18 +494,16 @@ class SmartButton implements SmartButtonInterface { add_action( $this->pay_order_renderer_hook(), function (): void { - $this->button_renderer( PayPalGateway::ID ); + $this->button_renderer( PayPalGateway::ID, 'woocommerce_paypal_payments_payorder_button_render' ); $this->button_renderer( CardButtonGateway::ID ); - do_action( 'woocommerce_paypal_payments_payorder_button_render' ); }, 20 ); add_action( $this->checkout_button_renderer_hook(), function (): void { - $this->button_renderer( PayPalGateway::ID ); + $this->button_renderer( PayPalGateway::ID, 'woocommerce_paypal_payments_checkout_button_render' ); $this->button_renderer( CardButtonGateway::ID ); - do_action( 'woocommerce_paypal_payments_checkout_button_render' ); } ); @@ -518,8 +515,7 @@ class SmartButton implements SmartButtonInterface { return; } - $this->button_renderer( PayPalGateway::ID ); - do_action( 'woocommerce_paypal_payments_cart_button_render' ); + $this->button_renderer( PayPalGateway::ID, 'woocommerce_paypal_payments_cart_button_render' ); }, 20 ); @@ -622,9 +618,10 @@ class SmartButton implements SmartButtonInterface { /** * Renders the HTML for the buttons. * - * @param string $gateway_id The gateway ID, like 'ppcp-gateway'. + * @param string $gateway_id The gateway ID, like 'ppcp-gateway'. + * @param string|null $action_name The action name to be called. */ - public function button_renderer( string $gateway_id ) { + public function button_renderer( string $gateway_id, string $action_name = null ) { $available_gateways = WC()->payment_gateways->get_available_payment_gateways(); @@ -634,7 +631,14 @@ class SmartButton implements SmartButtonInterface { // The wrapper is needed for the loading spinner, // otherwise jQuery block() prevents buttons rendering. - echo '
'; + echo '
'; + echo '
'; + + if ( null !== $action_name ) { + do_action( $action_name ); + } + + echo '
'; } /** From 4c4e4f14ffcddf24149e5028d541a78714cfa0b6 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 7 Sep 2023 16:56:10 +0100 Subject: [PATCH 2/3] Add hide/show/enable/disable triggers to button helpers --- .../js/modules/Helper/ButtonDisabler.js | 29 +++++++++++++++++-- .../resources/js/modules/Helper/Hiding.js | 24 +++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js b/modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js index ae7f3665c..b05a4dc70 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js +++ b/modules/ppcp-button/resources/js/modules/Helper/ButtonDisabler.js @@ -9,6 +9,24 @@ const getElement = (selectorOrElement) => { return selectorOrElement; } +const triggerEnabled = (selectorOrElement, element) => { + jQuery(document).trigger('ppcp-enabled', { + 'handler': 'ButtonsDisabler.setEnabled', + 'action': 'enable', + 'selector': selectorOrElement, + 'element': element + }); +} + +const triggerDisabled = (selectorOrElement, element) => { + jQuery(document).trigger('ppcp-disabled', { + 'handler': 'ButtonsDisabler.setEnabled', + 'action': 'disable', + 'selector': selectorOrElement, + 'element': element + }); +} + export const setEnabled = (selectorOrElement, enable, form = null) => { const element = getElement(selectorOrElement); @@ -17,7 +35,8 @@ export const setEnabled = (selectorOrElement, enable, form = null) => { } if (enable) { - jQuery(element).css({ + jQuery(element).removeClass('ppcp-disabled') + .css({ 'cursor': '', '-webkit-filter': '', 'filter': '', @@ -25,8 +44,12 @@ export const setEnabled = (selectorOrElement, enable, form = null) => { .off('mouseup') .find('> *') .css('pointer-events', ''); + + triggerEnabled(selectorOrElement, element); + } else { - jQuery(element).css({ + jQuery(element).addClass('ppcp-disabled') + .css({ 'cursor': 'not-allowed', '-webkit-filter': 'grayscale(100%)', 'filter': 'grayscale(100%)', @@ -44,6 +67,8 @@ export const setEnabled = (selectorOrElement, enable, form = null) => { }) .find('> *') .css('pointer-events', 'none'); + + triggerDisabled(selectorOrElement, element); } }; diff --git a/modules/ppcp-button/resources/js/modules/Helper/Hiding.js b/modules/ppcp-button/resources/js/modules/Helper/Hiding.js index 96836de0c..9ffd5a031 100644 --- a/modules/ppcp-button/resources/js/modules/Helper/Hiding.js +++ b/modules/ppcp-button/resources/js/modules/Helper/Hiding.js @@ -9,6 +9,24 @@ const getElement = (selectorOrElement) => { return selectorOrElement; } +const triggerHidden = (handler, selectorOrElement, element) => { + jQuery(document).trigger('ppcp-hidden', { + 'handler': handler, + 'action': 'hide', + 'selector': selectorOrElement, + 'element': element + }); +} + +const triggerShown = (handler, selectorOrElement, element) => { + jQuery(document).trigger('ppcp-shown', { + 'handler': handler, + 'action': 'show', + 'selector': selectorOrElement, + 'element': element + }); +} + export const isVisible = (element) => { return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length); } @@ -27,14 +45,18 @@ export const setVisible = (selectorOrElement, show, important = false) => { } element.style.setProperty('display', 'none', important ? 'important' : ''); + triggerHidden('Hiding.setVisible', selectorOrElement, element); + } else { if (currentValue === 'none') { element.style.removeProperty('display'); + triggerShown('Hiding.setVisible', selectorOrElement, element); } // still not visible (if something else added display: none in CSS) if (!isVisible(element)) { element.style.setProperty('display', 'block'); + triggerShown('Hiding.setVisible', selectorOrElement, element); } } }; @@ -47,8 +69,10 @@ export const setVisibleByClass = (selectorOrElement, show, hiddenClass) => { if (show) { element.classList.remove(hiddenClass); + triggerShown('Hiding.setVisibleByClass', selectorOrElement, element); } else { element.classList.add(hiddenClass); + triggerHidden('Hiding.setVisibleByClass', selectorOrElement, element); } }; From 75a092175b6272b9d6a3acdfa1b6b0ec4255c4cb Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 7 Sep 2023 17:03:12 +0100 Subject: [PATCH 3/3] Refactor block register context event handler --- modules/ppcp-blocks/resources/js/checkout-block.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-blocks/resources/js/checkout-block.js b/modules/ppcp-blocks/resources/js/checkout-block.js index c8441c624..583787821 100644 --- a/modules/ppcp-blocks/resources/js/checkout-block.js +++ b/modules/ppcp-blocks/resources/js/checkout-block.js @@ -29,7 +29,15 @@ const PayPalComponent = ({ if (!loaded) { loadPaypalScript(config.scriptData, () => { setLoaded(true); - buttonModuleWatcher.registerContextBootstrap(config.scriptData.context, this); + + buttonModuleWatcher.registerContextBootstrap(config.scriptData.context, { + createOrder: () => { + return createOrder(); + }, + onApprove: (data, actions) => { + return handleApprove(data, actions); + }, + }); }); } }, [loaded]);