Refactor payments to allow management of methods (https://github.com/woocommerce/woocommerce-admin/pull/6786)
* Add manage button for enabled and configured payments * Enable methods only instead of toggling * Update payment methods location * Move ribbon to separate component * Move setup container to separate component * Move payment action to separate component * Refactor payments to functional component * Fix missing action props * Fix broken onsetup callback * Update payment method keys to match management pages * Add changelog and testing instructions * Revert key changes in favor of manageUrl * Update e2e tests for payments
This commit is contained in:
parent
3745a6a74e
commit
eb6186a29c
|
@ -11,6 +11,15 @@
|
|||
5. Navigate to Homescreen.
|
||||
6. Navigate back to previous Analytics Report.
|
||||
7. Ensure that the time period is _still_ what you set on step 2.
|
||||
### Refactor payments to allow management of methods #6786
|
||||
|
||||
1. Do not select "CBD industry" as a store industry during onboarding.
|
||||
2. Make various payment methods visible by switching to different countries.
|
||||
3. Attempt to set up various payment methods.
|
||||
4. Make sure that after setup, a `Manage` link is shown that links to the payment method settings page.
|
||||
5. Check that simple methods like, cash delivery or bank transfer initially have an `Enable` option.
|
||||
|
||||
### Fix varation bug with Products reports #6647
|
||||
|
||||
### Fix varation bug with Products reports #6647
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ const StoreAlerts = lazy( () =>
|
|||
|
||||
const WCPayUsageModal = lazy( () =>
|
||||
import(
|
||||
/* webpackChunkName: "wcpay-usage-modal" */ '../task-list/tasks/payments/wcpay/wcpay-usage-modal'
|
||||
/* webpackChunkName: "wcpay-usage-modal" */ '../task-list/tasks/payments/methods/wcpay/wcpay-usage-modal'
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import { AppIllustration } from '../app-illustration';
|
|||
import './style.scss';
|
||||
import { setAllPropsToValue } from '~/lib/collections';
|
||||
import { getCountryCode } from '~/dashboard/utils';
|
||||
import { isWCPaySupported } from '~/task-list/tasks/payments/wcpay';
|
||||
import { isWCPaySupported } from '~/task-list/tasks/payments/methods/wcpay';
|
||||
|
||||
const generatePluginDescriptionWithLink = (
|
||||
description,
|
||||
|
|
|
@ -24,7 +24,7 @@ import Payments from './tasks/payments';
|
|||
import {
|
||||
installActivateAndConnectWcpay,
|
||||
isWCPaySupported,
|
||||
} from './tasks/payments/wcpay';
|
||||
} from './tasks/payments/methods/wcpay';
|
||||
import { groupListOfObjectsBy } from '../lib/collections';
|
||||
import { getLinkTypeAndHref } from '~/store-management-links';
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Button, Spinner } from '@wordpress/components';
|
||||
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
||||
import { updateQueryString } from '@woocommerce/navigation';
|
||||
import { useState } from '@wordpress/element';
|
||||
|
||||
export const Action = ( {
|
||||
hasSetup = false,
|
||||
isConfigured = false,
|
||||
isEnabled = false,
|
||||
isLoading = false,
|
||||
isRecommended = false,
|
||||
manageUrl = null,
|
||||
markConfigured,
|
||||
methodKey,
|
||||
onSetUp = () => {},
|
||||
onSetupCallback,
|
||||
} ) => {
|
||||
const [ isBusy, setIsBusy ] = useState( false );
|
||||
|
||||
const classes = 'woocommerce-task-payment__action';
|
||||
|
||||
if ( isLoading ) {
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
const handleClick = async () => {
|
||||
onSetUp( methodKey );
|
||||
|
||||
if ( onSetupCallback ) {
|
||||
setIsBusy( true );
|
||||
await new Promise( onSetupCallback )
|
||||
.then( () => {
|
||||
setIsBusy( false );
|
||||
} )
|
||||
.catch( () => {
|
||||
setIsBusy( false );
|
||||
} );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
updateQueryString( {
|
||||
method: methodKey,
|
||||
} );
|
||||
};
|
||||
|
||||
if ( hasSetup && ! isConfigured ) {
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
className={ classes }
|
||||
isPrimary={ isRecommended }
|
||||
isSecondary={ ! isRecommended }
|
||||
isBusy={ isBusy }
|
||||
disabled={ isBusy }
|
||||
onClick={ () => handleClick() }
|
||||
>
|
||||
{ __( 'Set up', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if ( ( hasSetup && isConfigured ) || ( ! hasSetup && isEnabled ) ) {
|
||||
if ( ! manageUrl ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
className={ classes }
|
||||
isSecondary
|
||||
href={ getAdminLink(
|
||||
'admin.php?page=wc-settings&tab=checkout§ion=' +
|
||||
methodKey
|
||||
) }
|
||||
>
|
||||
{ __( 'Manage', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={ classes }
|
||||
isSecondary
|
||||
onClick={ () => markConfigured( methodKey ) }
|
||||
>
|
||||
{ __( 'Enable', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
);
|
||||
};
|
|
@ -1,41 +1,28 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import { cloneElement, Component } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
CardBody,
|
||||
CardMedia,
|
||||
CardFooter,
|
||||
FormToggle,
|
||||
Spinner,
|
||||
} from '@wordpress/components';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import { H, Plugins } from '@woocommerce/components';
|
||||
import {
|
||||
getHistory,
|
||||
getNewPath,
|
||||
updateQueryString,
|
||||
} from '@woocommerce/navigation';
|
||||
import { Card, CardBody, CardMedia, CardFooter } from '@wordpress/components';
|
||||
import { useDispatch, useSelect } from '@wordpress/data';
|
||||
import { H } from '@woocommerce/components';
|
||||
import { getHistory, getNewPath } from '@woocommerce/navigation';
|
||||
import {
|
||||
ONBOARDING_STORE_NAME,
|
||||
OPTIONS_STORE_NAME,
|
||||
PLUGINS_STORE_NAME,
|
||||
pluginNames,
|
||||
SETTINGS_STORE_NAME,
|
||||
} from '@woocommerce/data';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
import { useMemo, useState } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { createNoticesFromResponse } from '../../../lib/notices';
|
||||
import { Action } from './action';
|
||||
import { getCountryCode } from '../../../dashboard/utils';
|
||||
import { getPaymentMethods } from './methods';
|
||||
import { RecommendedRibbon } from './recommended-ribbon';
|
||||
import { Setup } from './setup';
|
||||
|
||||
export const setMethodEnabledOption = async (
|
||||
optionName,
|
||||
|
@ -57,331 +44,19 @@ export const setMethodEnabledOption = async (
|
|||
}
|
||||
};
|
||||
|
||||
class Payments extends Component {
|
||||
constructor( props ) {
|
||||
super( ...arguments );
|
||||
const { methods } = props;
|
||||
|
||||
const enabledMethods = {};
|
||||
methods.forEach(
|
||||
( method ) => ( enabledMethods[ method.key ] = method.isEnabled )
|
||||
);
|
||||
this.state = {
|
||||
busyMethod: null,
|
||||
enabledMethods,
|
||||
recommendedMethod: this.getRecommendedMethod(),
|
||||
};
|
||||
|
||||
this.markConfigured = this.markConfigured.bind( this );
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { recommendedMethod } = this.state;
|
||||
|
||||
const method = this.getRecommendedMethod();
|
||||
if ( recommendedMethod !== method ) {
|
||||
this.setState( {
|
||||
recommendedMethod: method,
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
getRecommendedMethod() {
|
||||
const { methods } = this.props;
|
||||
const recommendedMethod = methods.find(
|
||||
( m ) =>
|
||||
( m.key === 'wcpay' && m.visible ) ||
|
||||
( m.key === 'mercadopago' && m.visible )
|
||||
);
|
||||
if ( ! recommendedMethod ) {
|
||||
return 'stripe';
|
||||
}
|
||||
return recommendedMethod.key;
|
||||
}
|
||||
|
||||
async markConfigured( methodName, queryParams = {} ) {
|
||||
const { enabledMethods } = this.state;
|
||||
const { methods } = this.props;
|
||||
|
||||
const method = methods.find( ( option ) => option.key === methodName );
|
||||
|
||||
if ( ! method ) {
|
||||
throw `Method ${ methodName } not found in available methods list`;
|
||||
}
|
||||
|
||||
this.setState( {
|
||||
enabledMethods: {
|
||||
...enabledMethods,
|
||||
[ methodName ]: true,
|
||||
},
|
||||
} );
|
||||
|
||||
await setMethodEnabledOption( method.optionName, 'yes', this.props );
|
||||
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: methodName,
|
||||
} );
|
||||
|
||||
getHistory().push(
|
||||
getNewPath( { ...queryParams, task: 'payments' }, '/', {} )
|
||||
);
|
||||
}
|
||||
|
||||
getCurrentMethod() {
|
||||
const { methods, query } = this.props;
|
||||
|
||||
if ( ! query.method ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentMethod = methods.find(
|
||||
( method ) => method.key === query.method
|
||||
);
|
||||
|
||||
if ( ! currentMethod ) {
|
||||
throw `Current method ${ query.method } not found in available methods list`;
|
||||
}
|
||||
|
||||
return currentMethod;
|
||||
}
|
||||
|
||||
getInstallStep() {
|
||||
const currentMethod = this.getCurrentMethod();
|
||||
|
||||
if ( ! currentMethod.plugins || ! currentMethod.plugins.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { activePlugins } = this.props;
|
||||
const pluginsToInstall = currentMethod.plugins.filter(
|
||||
( method ) => ! activePlugins.includes( method )
|
||||
);
|
||||
const pluginNamesString = currentMethod.plugins
|
||||
.map( ( pluginSlug ) => pluginNames[ pluginSlug ] )
|
||||
.join( ' ' + __( 'and', 'woocommerce-admin' ) + ' ' );
|
||||
|
||||
return {
|
||||
key: 'install',
|
||||
label: sprintf(
|
||||
__( 'Install %s', 'woocommerce-admin' ),
|
||||
pluginNamesString
|
||||
),
|
||||
content: (
|
||||
<Plugins
|
||||
onComplete={ ( plugins, response ) => {
|
||||
createNoticesFromResponse( response );
|
||||
recordEvent( 'tasklist_payment_install_method', {
|
||||
plugins: currentMethod.plugins,
|
||||
} );
|
||||
} }
|
||||
onError={ ( errors, response ) =>
|
||||
createNoticesFromResponse( response )
|
||||
}
|
||||
autoInstall
|
||||
pluginSlugs={ currentMethod.plugins }
|
||||
/>
|
||||
),
|
||||
isComplete: ! pluginsToInstall.length,
|
||||
};
|
||||
}
|
||||
|
||||
async toggleMethod( key ) {
|
||||
const { methods } = this.props;
|
||||
const { enabledMethods } = this.state;
|
||||
const method = methods.find( ( option ) => option.key === key );
|
||||
|
||||
if ( ! method ) {
|
||||
throw `Method ${ key } not found in available methods list`;
|
||||
}
|
||||
|
||||
enabledMethods[ key ] = ! enabledMethods[ key ];
|
||||
this.setState( { enabledMethods } );
|
||||
|
||||
recordEvent( 'tasklist_payment_toggle', {
|
||||
enabled: ! method.isEnabled,
|
||||
payment_method: key,
|
||||
} );
|
||||
|
||||
await setMethodEnabledOption(
|
||||
method.optionName,
|
||||
method.isEnabled ? 'no' : 'yes',
|
||||
this.props
|
||||
);
|
||||
}
|
||||
|
||||
async handleClick( method ) {
|
||||
const { methods } = this.props;
|
||||
const { key, onClick } = method;
|
||||
|
||||
recordEvent( 'tasklist_payment_setup', {
|
||||
options: methods.map( ( option ) => option.key ),
|
||||
selected: key,
|
||||
} );
|
||||
|
||||
if ( onClick ) {
|
||||
this.setState( { busyMethod: key } );
|
||||
await new Promise( onClick )
|
||||
.then( () => {
|
||||
this.setState( { busyMethod: null } );
|
||||
} )
|
||||
.catch( () => {
|
||||
this.setState( { busyMethod: null } );
|
||||
} );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
updateQueryString( {
|
||||
method: key,
|
||||
} );
|
||||
}
|
||||
|
||||
getSetupButtons( method ) {
|
||||
const { busyMethod, enabledMethods, recommendedMethod } = this.state;
|
||||
const { container, isConfigured, key } = method;
|
||||
if ( container && ! isConfigured ) {
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
isPrimary={ key === recommendedMethod }
|
||||
isSecondary={ key !== recommendedMethod }
|
||||
isBusy={ busyMethod === key }
|
||||
disabled={ busyMethod }
|
||||
onClick={ () => this.handleClick( method ) }
|
||||
>
|
||||
{ __( 'Set up', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<FormToggle
|
||||
checked={ enabledMethods[ key ] }
|
||||
onChange={ () => this.toggleMethod( key ) }
|
||||
onClick={ ( e ) => e.stopPropagation() }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const currentMethod = this.getCurrentMethod();
|
||||
const { recommendedMethod } = this.state;
|
||||
const { methods, query } = this.props;
|
||||
|
||||
if ( currentMethod ) {
|
||||
return (
|
||||
<Card className="woocommerce-task-payment-method woocommerce-task-card">
|
||||
<CardBody>
|
||||
{ cloneElement( currentMethod.container, {
|
||||
methodConfig: currentMethod,
|
||||
query,
|
||||
installStep: this.getInstallStep(),
|
||||
markConfigured: this.markConfigured,
|
||||
hasCbdIndustry: currentMethod.hasCbdIndustry,
|
||||
} ) }
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="woocommerce-task-payments">
|
||||
{ methods.map( ( method ) => {
|
||||
const {
|
||||
before,
|
||||
content,
|
||||
isConfigured,
|
||||
key,
|
||||
title,
|
||||
visible,
|
||||
loading,
|
||||
} = method;
|
||||
|
||||
if ( ! visible ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const classes = classnames(
|
||||
'woocommerce-task-payment',
|
||||
'woocommerce-task-card',
|
||||
! isConfigured &&
|
||||
'woocommerce-task-payment-not-configured',
|
||||
'woocommerce-task-payment-' + key
|
||||
);
|
||||
|
||||
const isRecommended =
|
||||
key === recommendedMethod && ! isConfigured;
|
||||
const showRecommendedRibbon =
|
||||
isRecommended && key !== 'wcpay';
|
||||
const showRecommendedPill =
|
||||
isRecommended && key === 'wcpay';
|
||||
const recommendedText =
|
||||
key === 'mercadopago'
|
||||
? __( 'Local Partner', 'woocommerce-admin' )
|
||||
: __( 'Recommended', 'woocommerce-admin' );
|
||||
|
||||
return (
|
||||
<Card key={ key } className={ classes }>
|
||||
{ showRecommendedRibbon && (
|
||||
<div className="woocommerce-task-payment__recommended-ribbon">
|
||||
<span>{ recommendedText }</span>
|
||||
</div>
|
||||
) }
|
||||
<CardMedia isBorderless>{ before }</CardMedia>
|
||||
<CardBody>
|
||||
<H className="woocommerce-task-payment__title">
|
||||
{ title }
|
||||
{ showRecommendedPill && (
|
||||
<span className="woocommerce-task-payment__recommended-pill">
|
||||
{ recommendedText }
|
||||
</span>
|
||||
) }
|
||||
</H>
|
||||
<div className="woocommerce-task-payment__content">
|
||||
{ content }
|
||||
</div>
|
||||
</CardBody>
|
||||
<CardFooter isBorderless>
|
||||
{ loading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
this.getSetupButtons( method )
|
||||
) }
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
} ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
export const Payments = ( { query } ) => {
|
||||
const { createNotice } = useDispatch( 'core/notices' );
|
||||
const {
|
||||
installAndActivatePlugins,
|
||||
invalidateResolutionForStoreSelector: invalidatePluginStoreSelector,
|
||||
} = dispatch( PLUGINS_STORE_NAME );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
} = useDispatch( PLUGINS_STORE_NAME );
|
||||
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
|
||||
const {
|
||||
invalidateResolution,
|
||||
invalidateResolutionForStoreSelector,
|
||||
} = dispatch( ONBOARDING_STORE_NAME );
|
||||
invalidateResolution( 'getProfileItems', [] );
|
||||
invalidateResolution( 'getTasksStatus', [] );
|
||||
return {
|
||||
clearTaskStatusCache: () => {
|
||||
invalidateResolutionForStoreSelector( 'getTasksStatus' );
|
||||
invalidatePluginStoreSelector( 'getPaypalOnboardingStatus' );
|
||||
},
|
||||
createNotice,
|
||||
installAndActivatePlugins,
|
||||
updateOptions,
|
||||
};
|
||||
} ),
|
||||
withSelect( ( select, props ) => {
|
||||
const { createNotice, installAndActivatePlugins } = props;
|
||||
} = useDispatch( ONBOARDING_STORE_NAME );
|
||||
|
||||
const { methods, options } = useSelect( ( select ) => {
|
||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
const {
|
||||
|
@ -419,7 +94,7 @@ export default compose(
|
|||
'woocommerce_woo-mercado-pago-basic_settings',
|
||||
];
|
||||
|
||||
const options = optionNames.reduce( ( result, name ) => {
|
||||
const retrievedOptions = optionNames.reduce( ( result, name ) => {
|
||||
result[ name ] = getOption( name );
|
||||
return result;
|
||||
}, {} );
|
||||
|
@ -433,27 +108,174 @@ export default compose(
|
|||
? getPaypalOnboardingStatus()
|
||||
: null;
|
||||
|
||||
const methods = getPaymentMethods( {
|
||||
return {
|
||||
methods: getPaymentMethods( {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
createNotice,
|
||||
installAndActivatePlugins,
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
onboardingStatus,
|
||||
options,
|
||||
options: retrievedOptions,
|
||||
profileItems,
|
||||
paypalOnboardingStatus,
|
||||
loadingPaypalStatus:
|
||||
! hasFinishedResolution( 'getPaypalOnboardingStatus' ) &&
|
||||
! paypalOnboardingStatus,
|
||||
} ),
|
||||
options: retrievedOptions,
|
||||
};
|
||||
} );
|
||||
|
||||
return {
|
||||
countryCode,
|
||||
profileItems,
|
||||
activePlugins,
|
||||
options,
|
||||
methods,
|
||||
const [ enabledMethods, setEnabledMethods ] = useState(
|
||||
methods.reduce( ( acc, method ) => {
|
||||
acc[ method.key ] = method.isEnabled;
|
||||
return acc;
|
||||
}, {} )
|
||||
);
|
||||
|
||||
const recommendedMethod = useMemo( () => {
|
||||
const method = methods.find(
|
||||
( m ) =>
|
||||
( m.key === 'wcpay' && m.visible ) ||
|
||||
( m.key === 'mercadopago' && m.visible )
|
||||
);
|
||||
if ( ! method ) {
|
||||
return 'stripe';
|
||||
}
|
||||
return method.key;
|
||||
}, [ methods ] );
|
||||
|
||||
const markConfigured = async ( methodKey, queryParams = {} ) => {
|
||||
const method = methods.find( ( option ) => option.key === methodKey );
|
||||
|
||||
if ( ! method ) {
|
||||
throw `Method ${ methodKey } not found in available methods list`;
|
||||
}
|
||||
|
||||
setEnabledMethods( {
|
||||
...enabledMethods,
|
||||
[ methodKey ]: true,
|
||||
} );
|
||||
|
||||
const clearTaskStatusCache = () => {
|
||||
invalidateResolution( 'getProfileItems', [] );
|
||||
invalidateResolution( 'getTasksStatus', [] );
|
||||
invalidateResolutionForStoreSelector( 'getTasksStatus' );
|
||||
invalidatePluginStoreSelector( 'getPaypalOnboardingStatus' );
|
||||
};
|
||||
|
||||
await setMethodEnabledOption( method.optionName, 'yes', {
|
||||
clearTaskStatusCache,
|
||||
updateOptions,
|
||||
options,
|
||||
} );
|
||||
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: methodKey,
|
||||
} );
|
||||
|
||||
getHistory().push(
|
||||
getNewPath( { ...queryParams, task: 'payments' }, '/', {} )
|
||||
);
|
||||
};
|
||||
|
||||
const currentMethod = useMemo( () => {
|
||||
if ( ! query.method ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const method = methods.find( ( m ) => m.key === query.method );
|
||||
|
||||
if ( ! method ) {
|
||||
throw `Current method ${ query.method } not found in available methods list`;
|
||||
}
|
||||
|
||||
return method;
|
||||
}, [ query ] );
|
||||
|
||||
if ( currentMethod ) {
|
||||
return (
|
||||
<Setup method={ currentMethod } markConfigured={ markConfigured } />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="woocommerce-task-payments">
|
||||
{ methods.map( ( method ) => {
|
||||
const {
|
||||
before,
|
||||
container,
|
||||
content,
|
||||
isConfigured,
|
||||
key,
|
||||
manageUrl,
|
||||
title,
|
||||
visible,
|
||||
loading,
|
||||
onClick,
|
||||
} = method;
|
||||
|
||||
if ( ! visible ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const classes = classnames(
|
||||
'woocommerce-task-payment',
|
||||
'woocommerce-task-card',
|
||||
! isConfigured && 'woocommerce-task-payment-not-configured',
|
||||
'woocommerce-task-payment-' + key
|
||||
);
|
||||
|
||||
const isRecommended =
|
||||
key === recommendedMethod && ! isConfigured;
|
||||
|
||||
return (
|
||||
<Card key={ key } className={ classes }>
|
||||
{ isRecommended && key !== 'wcpay' && (
|
||||
<RecommendedRibbon methodKey={ key } />
|
||||
) }
|
||||
<CardMedia isBorderless>{ before }</CardMedia>
|
||||
<CardBody>
|
||||
<H className="woocommerce-task-payment__title">
|
||||
{ title }
|
||||
{ isRecommended && key === 'wcpay' && (
|
||||
<RecommendedRibbon
|
||||
isPill
|
||||
methodKey={ key }
|
||||
/>
|
||||
) }
|
||||
</H>
|
||||
<div className="woocommerce-task-payment__content">
|
||||
{ content }
|
||||
</div>
|
||||
</CardBody>
|
||||
<CardFooter isBorderless>
|
||||
<Action
|
||||
manageUrl={ manageUrl }
|
||||
methodKey={ key }
|
||||
hasSetup={ !! container }
|
||||
isConfigured={ isConfigured }
|
||||
isEnabled={ enabledMethods[ key ] }
|
||||
isRecommended={ isRecommended }
|
||||
isLoading={ loading }
|
||||
markConfigured={ markConfigured }
|
||||
onSetup={ () =>
|
||||
recordEvent( 'tasklist_payment_setup', {
|
||||
options: methods.map(
|
||||
( option ) => option.key
|
||||
),
|
||||
selected: key,
|
||||
} )
|
||||
)( Payments );
|
||||
}
|
||||
onSetupCallback={ onClick }
|
||||
/>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
} ) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Payments;
|
||||
|
|
|
@ -14,12 +14,12 @@ import { Link } from '@woocommerce/components';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Bacs from './bacs';
|
||||
import BacsLogo from './images/bacs';
|
||||
import CodLogo from './images/cod';
|
||||
import WCPayLogo from './images/wcpay';
|
||||
import RazorpayLogo from './images/razorpay';
|
||||
import { MollieLogo } from './images/mollie';
|
||||
import { PayUIndiaLogo } from './images/payu-india';
|
||||
import BacsLogo from '../images/bacs';
|
||||
import CodLogo from '../images/cod';
|
||||
import WCPayLogo from '../images/wcpay';
|
||||
import RazorpayLogo from '../images/razorpay';
|
||||
import { MollieLogo } from '../images/mollie';
|
||||
import { PayUIndiaLogo } from '../images/payu-india';
|
||||
import Stripe from './stripe';
|
||||
import Square from './square';
|
||||
import {
|
||||
|
@ -35,10 +35,16 @@ import EWay from './eway';
|
|||
import Razorpay from './razorpay';
|
||||
import { Mollie } from './mollie';
|
||||
import { PayUIndia } from './payu-india';
|
||||
import { GenericPaymentStep } from './generic-payment-step';
|
||||
import { GenericPaymentStep } from '../generic-payment-step';
|
||||
|
||||
const wcAdminAssetUrl = getSetting( 'wcAdminAssetUrl', '' );
|
||||
|
||||
const getPaymentsSettingsUrl = ( methodKey ) => {
|
||||
return getAdminLink(
|
||||
'admin.php?page=wc-settings&tab=checkout§ion=' + methodKey
|
||||
);
|
||||
};
|
||||
|
||||
export function getPaymentMethods( {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
|
@ -98,6 +104,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_stripe_settings &&
|
||||
options.woocommerce_stripe_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_stripe_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'stripe' ),
|
||||
},
|
||||
{
|
||||
key: 'paystack',
|
||||
|
@ -149,6 +156,7 @@ export function getPaymentMethods( {
|
|||
},
|
||||
};
|
||||
},
|
||||
manageUrl: getPaymentsSettingsUrl( 'paystack' ),
|
||||
},
|
||||
{
|
||||
key: 'payfast',
|
||||
|
@ -209,6 +217,7 @@ export function getPaymentMethods( {
|
|||
},
|
||||
};
|
||||
},
|
||||
manageUrl: getPaymentsSettingsUrl( 'stripe' ),
|
||||
},
|
||||
{
|
||||
key: 'mercadopago',
|
||||
|
@ -241,6 +250,7 @@ export function getPaymentMethods( {
|
|||
options[ 'woocommerce_woo-mercado-pago-basic_settings' ]
|
||||
.enabled === 'yes',
|
||||
optionName: 'woocommerce_woo-mercado-pago-basic_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'woo-mercado-pago-basic' ),
|
||||
},
|
||||
{
|
||||
key: 'paypal',
|
||||
|
@ -266,6 +276,7 @@ export function getPaymentMethods( {
|
|||
loading: activePlugins.includes( PAYPAL_PLUGIN )
|
||||
? loadingPaypalStatus
|
||||
: false,
|
||||
manageUrl: getPaymentsSettingsUrl( 'ppcp-gateway' ),
|
||||
},
|
||||
{
|
||||
key: 'klarna_checkout',
|
||||
|
@ -290,6 +301,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_kco_settings &&
|
||||
options.woocommerce_kco_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_kco_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'kco' ),
|
||||
},
|
||||
{
|
||||
key: 'klarna_payments',
|
||||
|
@ -325,6 +337,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_klarna_payments_settings &&
|
||||
options.woocommerce_klarna_payments_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_klarna_payments_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'klarna_payments' ),
|
||||
},
|
||||
{
|
||||
key: 'mollie',
|
||||
|
@ -360,6 +373,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_mollie_payments_settings &&
|
||||
options.woocommerce_mollie_payments_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_mollie_payments_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'mollie_wc_gateway_creditcard' ),
|
||||
},
|
||||
{
|
||||
key: 'square',
|
||||
|
@ -403,6 +417,7 @@ export function getPaymentMethods( {
|
|||
'yes',
|
||||
optionName: 'woocommerce_square_credit_card_settings',
|
||||
hasCbdIndustry,
|
||||
manageUrl: getPaymentsSettingsUrl( 'square_credit_card' ),
|
||||
},
|
||||
{
|
||||
key: 'eway',
|
||||
|
@ -432,6 +447,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_eway_settings &&
|
||||
options.woocommerce_eway_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_eway_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'eway' ),
|
||||
},
|
||||
{
|
||||
key: 'razorpay',
|
||||
|
@ -456,6 +472,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_razorpay_settings &&
|
||||
options.woocommerce_razorpay_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_razorpay_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'razorpay' ),
|
||||
},
|
||||
{
|
||||
key: 'payubiz',
|
||||
|
@ -475,6 +492,7 @@ export function getPaymentMethods( {
|
|||
isConfigured: activePlugins.includes( 'payu-india' ),
|
||||
isEnabled: enabledPaymentGateways.includes( 'payubiz' ),
|
||||
optionName: 'woocommerce_payubiz_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'payubiz' ),
|
||||
},
|
||||
{
|
||||
key: 'cod',
|
||||
|
@ -489,6 +507,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_cod_settings &&
|
||||
options.woocommerce_cod_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_cod_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'cod' ),
|
||||
},
|
||||
{
|
||||
key: 'bacs',
|
||||
|
@ -507,6 +526,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_bacs_settings &&
|
||||
options.woocommerce_bacs_settings.enabled === 'yes',
|
||||
optionName: 'woocommerce_bacs_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'bacs' ),
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -608,6 +628,7 @@ export function getPaymentMethods( {
|
|||
options.woocommerce_woocommerce_payments_settings.enabled ===
|
||||
'yes',
|
||||
optionName: 'woocommerce_woocommerce_payments_settings',
|
||||
manageUrl: getPaymentsSettingsUrl( 'woocommerce_payments' ),
|
||||
} );
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import { SETTINGS_STORE_NAME } from '@woocommerce/data';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getCountryCode } from '../../../dashboard/utils';
|
||||
import { getCountryCode } from '~/dashboard/utils';
|
||||
|
||||
export const MERCADOPAGO_PLUGIN = 'woocommerce-mercadopago';
|
||||
|
|
@ -9,7 +9,7 @@ import { recordEvent } from '@woocommerce/tracks';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { createNoticesFromResponse } from '../../../../lib/notices';
|
||||
import { createNoticesFromResponse } from '~/lib/notices';
|
||||
|
||||
export function installActivateAndConnectWcpay(
|
||||
reject,
|
|
@ -10,7 +10,7 @@ import { Link } from '@woocommerce/components';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import UsageModal from '../../../../profile-wizard/steps/usage-modal';
|
||||
import UsageModal from '~/profile-wizard/steps/usage-modal';
|
||||
|
||||
const WCPayUsageModal = () => {
|
||||
const query = getQuery();
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const localPartners = [ 'mercadopago' ];
|
||||
|
||||
export const RecommendedRibbon = ( { methodKey, isPill = false } ) => {
|
||||
const classes = isPill
|
||||
? 'woocommerce-task-payment__recommended-pill'
|
||||
: 'woocommerce-task-payment__recommended-ribbon';
|
||||
|
||||
const text = localPartners.includes( methodKey )
|
||||
? __( 'Local Partner', 'woocommerce-admin' )
|
||||
: __( 'Recommended', 'woocommerce-admin' );
|
||||
|
||||
return (
|
||||
<div className={ classes }>
|
||||
<span>{ text }</span>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Card, CardBody } from '@wordpress/components';
|
||||
import { cloneElement, useMemo } from '@wordpress/element';
|
||||
import { Plugins } from '@woocommerce/components';
|
||||
import { PLUGINS_STORE_NAME, pluginNames } from '@woocommerce/data';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { createNoticesFromResponse } from '~/lib/notices';
|
||||
|
||||
export const Setup = ( { method, markConfigured, query } ) => {
|
||||
const { activePlugins } = useSelect( ( select ) => {
|
||||
const { getActivePlugins } = select( PLUGINS_STORE_NAME );
|
||||
|
||||
return {
|
||||
activePlugins: getActivePlugins(),
|
||||
};
|
||||
} );
|
||||
|
||||
const installStep = useMemo( () => {
|
||||
if ( ! method.plugins || ! method.plugins.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pluginsToInstall = method.plugins.filter(
|
||||
( m ) => ! activePlugins.includes( m )
|
||||
);
|
||||
const pluginNamesString = method.plugins
|
||||
.map( ( pluginSlug ) => pluginNames[ pluginSlug ] )
|
||||
.join( ' ' + __( 'and', 'woocommerce-admin' ) + ' ' );
|
||||
|
||||
return {
|
||||
key: 'install',
|
||||
label: sprintf(
|
||||
/* translators: %s = one or more plugin names joined by "and" */
|
||||
__( 'Install %s', 'woocommerce-admin' ),
|
||||
pluginNamesString
|
||||
),
|
||||
content: (
|
||||
<Plugins
|
||||
onComplete={ ( plugins, response ) => {
|
||||
createNoticesFromResponse( response );
|
||||
recordEvent( 'tasklist_payment_install_method', {
|
||||
plugins: method.plugins,
|
||||
} );
|
||||
} }
|
||||
onError={ ( errors, response ) =>
|
||||
createNoticesFromResponse( response )
|
||||
}
|
||||
autoInstall
|
||||
pluginSlugs={ method.plugins }
|
||||
/>
|
||||
),
|
||||
isComplete: ! pluginsToInstall.length,
|
||||
};
|
||||
}, [ activePlugins, method.plugins ] );
|
||||
|
||||
if ( ! method.container ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="woocommerce-task-payment-method woocommerce-task-card">
|
||||
<CardBody>
|
||||
{ cloneElement( method.container, {
|
||||
methodConfig: method,
|
||||
query,
|
||||
installStep,
|
||||
markConfigured,
|
||||
hasCbdIndustry: method.hasCbdIndustry,
|
||||
} ) }
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
|
@ -8,7 +8,7 @@ import apiFetch from '@wordpress/api-fetch';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { PayPal, PAYPAL_PLUGIN } from '../tasks/payments/paypal';
|
||||
import { PayPal, PAYPAL_PLUGIN } from '../tasks/payments/methods/paypal';
|
||||
import { getPaymentMethods } from '../tasks/payments/methods';
|
||||
import { setMethodEnabledOption } from '../../task-list/tasks/payments';
|
||||
import { GenericPaymentStep } from '../tasks/payments/generic-payment-step';
|
||||
|
|
|
@ -80,6 +80,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt
|
|||
- Fix: Retain persisted queries when navigating to Homescreen #6614
|
||||
- Update: Update choose niche note cta URL #6733
|
||||
- Fix: Update folded header style #6724
|
||||
- Tweak: Refactor payments to allow management of methods #6786
|
||||
- Fix: Fix unreleated variations showing up in the Products reports #6647
|
||||
- Tweak: Add tracking data for the preview site btn #6623
|
||||
- Tweak: Update WC Payments copy on the task list #6734
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
import { waitForElementByText } from '../utils/actions';
|
||||
import { BasePage } from './BasePage';
|
||||
import { getElementByText } from '../utils/actions';
|
||||
|
||||
type PaymentMethodWithSetupButton =
|
||||
| 'wcpay'
|
||||
|
@ -39,15 +40,10 @@ export class PaymentsSetup extends BasePage {
|
|||
}
|
||||
|
||||
async methodHasBeenSetup( method: PaymentMethod ) {
|
||||
const toggle = this.getFormToggle(
|
||||
`.woocommerce-task-payment-${ method }`
|
||||
);
|
||||
|
||||
await toggle.isEnabled();
|
||||
await getElementByText( 'button', 'Manage', `.woocommerce-task-payment-${ method }` )
|
||||
}
|
||||
|
||||
async enableCashOnDelivery() {
|
||||
const toggle = this.getFormToggle( '.woocommerce-task-payment-cod' );
|
||||
await toggle.switchOn();
|
||||
await this.clickButtonWithText( 'Enable' );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ describe( 'Payment setup task', () => {
|
|||
await paymentsSetup.methodHasBeenSetup( 'bacs' );
|
||||
} );
|
||||
|
||||
it( 'Toggling cash on delivery enables the payment method', async () => {
|
||||
it( 'Enabling cash on delivery enables the payment method', async () => {
|
||||
await paymentsSetup.enableCashOnDelivery();
|
||||
await paymentsSetup.methodHasBeenSetup( 'cod' );
|
||||
} );
|
||||
|
|
Loading…
Reference in New Issue