Skip to content

Commit

Permalink
New Settings UI: Implement logic for features and refresh button.
Browse files Browse the repository at this point in the history
  • Loading branch information
hmouhtar committed Dec 16, 2024
1 parent 16ad84c commit e5159ec
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 16 deletions.
20 changes: 20 additions & 0 deletions modules/ppcp-googlepay/src/GooglepayModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,26 @@ function( array $locations, string $setting_name ): array {
2
);

add_filter(
'woocommerce_paypal_payments_rest_common_merchant_data',
function ( array $merchant_data ) use ( $c ): array {
if ( ! isset( $merchant_data['features'] ) ) {
$merchant_data['features'] = array();
}

$product_status = $c->get( 'googlepay.helpers.apm-product-status' );
assert( $product_status instanceof ApmProductStatus );

$google_pay_enabled = $product_status->is_active();

$merchant_data['features']['google_pay'] = array(
'enabled' => $google_pay_enabled,
);

return $merchant_data;
}
);

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
<Header>
<Title>
{ title }
{ props.actionProps?.featureStatus && (
{ props.actionProps?.enabled && (
<TitleBadge
{ ...props.actionProps?.badge }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,42 @@ import TodoSettingsBlock from '../../ReusableComponents/SettingsBlocks/TodoSetti
import FeatureSettingsBlock from '../../ReusableComponents/SettingsBlocks/FeatureSettingsBlock';
import { TITLE_BADGE_POSITIVE } from '../../ReusableComponents/TitleBadge';
import data from '../../../utils/data';
import { useMerchantInfo } from '../../../data/common/hooks';
import { useDispatch } from '@wordpress/data';
import { STORE_NAME } from '../../../data/common';

const TabOverview = () => {
const [ todos, setTodos ] = useState( [] );
const [ todosData, setTodosData ] = useState( todosDataDefault );
const [ isRefreshing, setIsRefreshing ] = useState( false );

const { merchant } = useMerchantInfo();
const { refreshFeatureStatuses } = useDispatch( STORE_NAME );

const features = featuresDefault.map( ( feature ) => {
const merchantFeature = merchant?.features?.[ feature.id ];
return {
...feature,
enabled: merchantFeature?.enabled ?? false,
};
} );

const refreshHandler = async () => {
setIsRefreshing( true );

const result = await refreshFeatureStatuses();

if ( result && ! result.success ) {
console.error(
'Failed to refresh features:',
result.message || 'Unknown error'
);
} else {
console.log( 'Features refreshed successfully.' );
}

setIsRefreshing( false );
};

return (
<div className="ppcp-r-tab-overview">
Expand Down Expand Up @@ -39,30 +71,54 @@ const TabOverview = () => {
title={ __( 'Features', 'woocommerce-paypal-payments' ) }
description={
<div>
<p>{ __( 'Enable additional features…' ) }</p>
<p>{ __( 'Click Refresh…' ) }</p>
<Button variant="tertiary">
<p>
{ __(
'Enable additional features…',
'woocommerce-paypal-payments'
) }
</p>
<p>
{ __(
'Click Refresh…',
'woocommerce-paypal-payments'
) }
</p>
<Button
variant="tertiary"
onClick={ refreshHandler }
disabled={ isRefreshing }
>
{ data().getImage( 'icon-refresh.svg' ) }
{ __( 'Refresh', 'woocommerce-paypal-payments' ) }
{ isRefreshing
? __(
'Refreshing…',
'woocommerce-paypal-payments'
)
: __(
'Refresh',
'woocommerce-paypal-payments'
) }
</Button>
</div>
}
contentItems={ featuresDefault.map( ( feature ) => (
contentItems={ features.map( ( feature ) => (
<FeatureSettingsBlock
key={ feature.id }
title={ feature.title }
description={ feature.description }
actionProps={ {
buttons: feature.buttons,
featureStatus: feature.featureStatus,
enabled: feature.enabled,
notes: feature.notes,
badge: {
text: __(
'Active',
'woocommerce-paypal-payments'
),
type: TITLE_BADGE_POSITIVE,
},
badge: feature.enabled
? {
text: __(
'Active',
'woocommerce-paypal-payments'
),
type: TITLE_BADGE_POSITIVE,
}
: undefined,
} }
/>
) ) }
Expand Down Expand Up @@ -133,7 +189,6 @@ const featuresDefault = [
'Advanced Credit and Debit Cards',
'woocommerce-paypal-payments'
),
featureStatus: true,
description: __(
'Process major credit and debit cards including Visa, Mastercard, American Express and Discover.',
'woocommerce-paypal-payments'
Expand Down Expand Up @@ -181,7 +236,6 @@ const featuresDefault = [
'Let customers pay using their Google Pay wallet.',
'woocommerce-paypal-payments'
),
featureStatus: true,
buttons: [
{
type: 'secondary',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ export default {
DO_SANDBOX_LOGIN: 'COMMON:DO_SANDBOX_LOGIN',
DO_PRODUCTION_LOGIN: 'COMMON:DO_PRODUCTION_LOGIN',
DO_REFRESH_MERCHANT: 'COMMON:DO_REFRESH_MERCHANT',
DO_REFRESH_FEATURES: 'DO_REFRESH_FEATURES',

This comment has been minimized.

Copy link
@stracker-phil

stracker-phil Dec 16, 2024

Collaborator

Please use the COMMON: prefix for the action type value, i.e.

DO_REFRESH_FEATURES: 'COMMON:DO_REFRESH_FEATURES',

};
11 changes: 11 additions & 0 deletions modules/ppcp-settings/resources/js/data/common/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,14 @@ export const connectViaIdAndSecret = function* () {
export const refreshMerchantData = function* () {
return yield { type: ACTION_TYPES.DO_REFRESH_MERCHANT };
};

/**
* Side effect.
* Purges all features status data via a REST request.
* Refreshes the merchant data via a REST request.
*
* @return {Action} The action.
*/
export const refreshFeatureStatuses = function* () {
return yield { type: ACTION_TYPES.DO_REFRESH_FEATURES };
};
11 changes: 11 additions & 0 deletions modules/ppcp-settings/resources/js/data/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,14 @@ export const REST_MANUAL_CONNECTION_PATH = '/wc/v3/wc_paypal/connect_manual';
* @type {string}
*/
export const REST_CONNECTION_URL_PATH = '/wc/v3/wc_paypal/login_link';

/**
* REST path to refresh the feature status.
*
* Used by: Controls
* See: RefreshFeatureStatusEndpoint.php
*
* @type {string}
*/
export const REST_REFRESH_FEATURES_PATH =
'/wc/v3/wc_paypal/refresh-feature-status';
24 changes: 24 additions & 0 deletions modules/ppcp-settings/resources/js/data/common/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
REST_MANUAL_CONNECTION_PATH,
REST_CONNECTION_URL_PATH,
REST_HYDRATE_MERCHANT_PATH,
REST_REFRESH_FEATURES_PATH,
} from './constants';
import ACTION_TYPES from './action-types';

Expand Down Expand Up @@ -121,4 +122,27 @@ export const controls = {

return result;
},

async [ ACTION_TYPES.DO_REFRESH_FEATURES ]() {
let result = null;

try {
result = await apiFetch( {
path: REST_REFRESH_FEATURES_PATH,
method: 'POST',
} );

if ( result.success ) {

This comment has been minimized.

Copy link
@stracker-phil

stracker-phil Dec 16, 2024

Collaborator

In our Redux store, we want to keep controls simple - they should return a value and not dispatch other actions.

Dispatching other actions should be handled in the action.js file, i.e. like that:

export const refreshFeatureStatuses = function* () {
	const result = yield { type: ACTION_TYPES.DO_REFRESH_FEATURES };
	if ( result.success ) {
		yield hydrate( result.data ) // Possibly `hydrate` is the right action, as we should only move the result.data details to the Redux store.
	}
	return result;
};

This comment has been minimized.

Copy link
@hmouhtar

hmouhtar Dec 16, 2024

Author Collaborator

@stracker-phil The refresh feature status endpoint does not return any data at the moment, my approach was chaining it with the refresh merchant data action... Do you agree with that approach? If so, I would only move the refreshMerchantData call to the refreshFeatureStatuses action instead of the control.

result = await dispatch( STORE_NAME ).refreshMerchantData();
}
} catch ( e ) {
result = {
success: false,
error: e,
message: e.message,
};
}

return result;
},
};
8 changes: 8 additions & 0 deletions modules/ppcp-settings/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use WooCommerce\PayPalCommerce\Settings\Endpoint\ConnectManualRestEndpoint;
use WooCommerce\PayPalCommerce\Settings\Endpoint\LoginLinkRestEndpoint;
use WooCommerce\PayPalCommerce\Settings\Endpoint\OnboardingRestEndpoint;
use WooCommerce\PayPalCommerce\Settings\Endpoint\RefreshFeatureStatusEndpoint;
use WooCommerce\PayPalCommerce\Settings\Endpoint\SwitchSettingsUiEndpoint;
use WooCommerce\PayPalCommerce\Settings\Service\ConnectionUrlGenerator;
use WooCommerce\PayPalCommerce\Settings\Service\OnboardingUrlManager;
Expand Down Expand Up @@ -70,6 +71,13 @@
'settings.rest.common' => static function ( ContainerInterface $container ) : CommonRestEndpoint {
return new CommonRestEndpoint( $container->get( 'settings.data.common' ) );
},
'settings.rest.refresh_feature_status' => static function ( ContainerInterface $container ) : RefreshFeatureStatusEndpoint {
return new RefreshFeatureStatusEndpoint(
$container->get( 'wcgateway.settings' ),
new Cache( 'ppcp-timeout' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
'settings.rest.connect_manual' => static function ( ContainerInterface $container ) : ConnectManualRestEndpoint {
return new ConnectManualRestEndpoint(
$container->get( 'api.paypal-host-production' ),
Expand Down
5 changes: 5 additions & 0 deletions modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ protected function add_merchant_info( array $extra_data ) : array {
$this->merchant_info_map
);

$extra_data['merchant'] = apply_filters(
'woocommerce_paypal_payments_rest_common_merchant_data',
$extra_data['merchant'],
);

return $extra_data;
}

Expand Down
Loading

0 comments on commit e5159ec

Please sign in to comment.