From 6c4c8fb7c192e078fb78c9b16cfae875498fe5cd Mon Sep 17 00:00:00 2001 From: Joshua T Flowers Date: Mon, 16 Mar 2020 12:09:29 +0100 Subject: [PATCH] Onboarding: Add toggles to configured payments in task list (https://github.com/woocommerce/woocommerce-admin/pull/3801) * Add isConfigured property to all payment methods * Remove payment configuration checks from server side * Add isEnabled flags to all payment methods * Add payment method toggle methods * Extract payment methods * Fix update options selectors * Add error handling for payment method updates * Remove configured from saved option * Add event when payment is toggled * Check if payment option exists before checking config * Only fetch PayPal connection URL when plugin is active * Only fetch Stripe connection URL when plugin is active --- .../task-list/tasks/payments/index.js | 319 +++++++----------- .../task-list/tasks/payments/methods.js | 198 +++++++++++ .../task-list/tasks/payments/paypal.js | 32 +- .../task-list/tasks/payments/stripe.js | 15 + .../client/wc-api/options/operations.js | 2 +- .../client/wc-api/options/selectors.js | 6 + .../src/Features/Onboarding.php | 6 + .../src/Features/OnboardingTasks.php | 92 +---- 8 files changed, 377 insertions(+), 293 deletions(-) create mode 100644 plugins/woocommerce-admin/client/dashboard/task-list/tasks/payments/methods.js diff --git a/plugins/woocommerce-admin/client/dashboard/task-list/tasks/payments/index.js b/plugins/woocommerce-admin/client/dashboard/task-list/tasks/payments/index.js index f71905c92ee..6ad044ffbe9 100644 --- a/plugins/woocommerce-admin/client/dashboard/task-list/tasks/payments/index.js +++ b/plugins/woocommerce-admin/client/dashboard/task-list/tasks/payments/index.js @@ -2,9 +2,8 @@ * External dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { Fragment, cloneElement, Component } from '@wordpress/element'; +import { cloneElement, Component } from '@wordpress/element'; import { compose } from '@wordpress/compose'; -import { get, filter } from 'lodash'; import { Button, FormToggle } from '@wordpress/components'; import { withDispatch } from '@wordpress/data'; @@ -17,10 +16,6 @@ import { getNewPath, updateQueryString, } from '@woocommerce/navigation'; -import { - WC_ASSET_URL as wcAssetUrl, - getSetting, -} from '@woocommerce/wc-admin-settings'; /** * Internal dependencies @@ -29,16 +24,21 @@ import { recordEvent } from 'lib/tracks'; import { getCountryCode } from 'dashboard/utils'; import withSelect from 'wc-api/with-select'; import Plugins from '../steps/plugins'; -import Stripe from './stripe'; -import Square from './square'; -import PayPal from './paypal'; import { pluginNames } from 'wc-api/onboarding/constants'; -import Klarna from './klarna'; -import PayFast from './payfast'; +import { getPaymentMethods } from './methods'; class Payments extends Component { - constructor() { + constructor( props ) { super( ...arguments ); + const { methods } = props; + + const enabledMethods = {}; + methods.forEach( + ( method ) => ( enabledMethods[ method.key ] = method.isEnabled ) + ); + this.state = { + enabledMethods, + }; this.recommendedMethod = 'stripe'; this.completeTask = this.completeTask.bind( this ); @@ -46,18 +46,43 @@ class Payments extends Component { this.skipTask = this.skipTask.bind( this ); } + componentDidUpdate( prevProps ) { + const { createNotice, errors, methods, requesting } = this.props; + + methods.forEach( ( method ) => { + const { key, title } = method; + if ( + prevProps.requesting[ key ] && + ! requesting[ key ] && + errors[ key ] + ) { + createNotice( + 'error', + sprintf( + __( + 'There was a problem updating settings for %s', + 'woocommerce-admin' + ), + title + ) + ); + } + } ); + } + completeTask() { - const { configured, createNotice, options, updateOptions } = this.props; + const { createNotice, methods, updateOptions } = this.props; updateOptions( { woocommerce_task_list_payments: { - ...options.woocommerce_task_list_payments, completed: 1, }, } ); recordEvent( 'tasklist_payment_done', { - configured, + configured: methods + .filter( ( method ) => method.isConfigured ) + .map( ( method ) => method.key ), } ); createNotice( @@ -72,199 +97,36 @@ class Payments extends Component { } skipTask() { - const { options, updateOptions } = this.props; + const { methods, updateOptions } = this.props; updateOptions( { woocommerce_task_list_payments: { - ...options.woocommerce_task_list_payments, completed: 1, }, } ); recordEvent( 'tasklist_payment_skip_task', { - options: this.getMethodOptions().map( ( method ) => method.key ), + options: methods.map( ( method ) => method.key ), } ); getHistory().push( getNewPath( {}, '/', {} ) ); } - isStripeEnabled() { - const { countryCode } = this.props; - const stripeCountries = getSetting( 'onboarding', { - stripeSupportedCountries: [], - } ).stripeSupportedCountries; - return stripeCountries.includes( countryCode ); - } - markConfigured( method ) { - const { options, configured, updateOptions } = this.props; - getHistory().push( getNewPath( { task: 'payments' }, '/', {} ) ); - if ( configured.includes( method ) ) { - return; - } - recordEvent( 'tasklist_payment_connect_method', { payment_method: method, } ); - - configured.push( method ); - updateOptions( { - woocommerce_task_list_payments: { - ...options.woocommerce_task_list_payments, - configured, - }, - } ); - } - - getMethodOptions() { - const { countryCode, profileItems } = this.props; - - const methods = [ - { - key: 'stripe', - title: __( - 'Credit cards - powered by Stripe', - 'woocommerce-admin' - ), - content: ( - - { __( - 'Accept debit and credit cards in 135+ currencies, methods such as Alipay, ' + - 'and one-touch checkout with Apple Pay.', - 'woocommerce-admin' - ) } - - ), - before: , - visible: this.isStripeEnabled(), - plugins: [ 'woocommerce-gateway-stripe' ], - container: , - }, - { - key: 'paypal', - title: __( 'PayPal Checkout', 'woocommerce-admin' ), - content: ( - - { __( - "Safe and secure payments using credit cards or your customer's PayPal account.", - 'woocommerce-admin' - ) } - - ), - before: , - visible: true, - plugins: [ 'woocommerce-gateway-paypal-express-checkout' ], - container: , - }, - { - key: 'klarna_checkout', - title: __( 'Klarna Checkout', 'woocommerce-admin' ), - content: __( - 'Choose the payment that you want, pay now, pay later or slice it. No credit card numbers, no passwords, no worries.', - 'woocommerce-admin' - ), - before: ( - - ), - visible: [ 'SE', 'FI', 'NO', 'NL' ].includes( countryCode ), - plugins: [ 'klarna-checkout-for-woocommerce' ], - container: ( - - ), - }, - { - key: 'klarna_payments', - title: __( 'Klarna Payments', 'woocommerce-admin' ), - content: __( - 'Choose the payment that you want, pay now, pay later or slice it. No credit card numbers, no passwords, no worries.', - 'woocommerce-admin' - ), - before: ( - - ), - visible: [ 'DK', 'DE', 'AT' ].includes( countryCode ), - plugins: [ 'klarna-payments-for-woocommerce' ], - container: ( - - ), - }, - { - key: 'square', - title: __( 'Square', 'woocommerce-admin' ), - content: __( - 'Securely accept credit and debit cards with one low rate, no surprise fees (custom rates available). ' + - 'Sell online and in store and track sales and inventory in one place.', - 'woocommerce-admin' - ), - before: ( - - ), - visible: - [ 'brick-mortar', 'brick-mortar-other' ].includes( - profileItems.selling_venues - ) && - [ 'US', 'CA', 'JP', 'GB', 'AU' ].includes( countryCode ), - plugins: [ 'woocommerce-square' ], - container: , - }, - { - key: 'payfast', - title: __( 'PayFast', 'woocommerce-admin' ), - content: ( - - { __( - 'The PayFast extension for WooCommerce enables you to accept payments by Credit Card and EFT via one of South Africa’s most popular payment gateways. No setup fees or monthly subscription costs.', - 'woocommerce-admin' - ) } -

- { __( - 'Selecting this extension will configure your store to use South African rands as the selected currency.', - 'woocommerce-admin' - ) } -

-
- ), - before: ( - PayFast logo - ), - visible: [ 'ZA' ].includes( countryCode ), - plugins: [ 'woocommerce-payfast-gateway' ], - container: , - }, - ]; - - return filter( methods, ( method ) => method.visible ); } getCurrentMethod() { - const { query } = this.props; + const { methods, query } = this.props; if ( ! query.method ) { return; } - const methods = this.getMethodOptions(); - return methods.find( ( method ) => method.key === query.method ); } @@ -304,9 +166,34 @@ class Payments extends Component { }; } + toggleMethod( key ) { + const { methods, options, updateOptions } = this.props; + const { enabledMethods } = this.state; + const method = methods.find( ( option ) => option.key === key ); + + enabledMethods[ key ] = ! enabledMethods[ key ]; + this.setState( { enabledMethods } ); + + recordEvent( 'tasklist_payment_toggle', { + enabled: ! method.isEnabled, + payment_method: key, + } ); + + updateOptions( { + [ method.optionName ]: { + ...options[ method.optionName ], + enabled: method.isEnabled ? 'no' : 'yes', + }, + } ); + } + render() { const currentMethod = this.getCurrentMethod(); - const { configured, query } = this.props; + const { methods, query } = this.props; + const { enabledMethods } = this.state; + const configuredMethods = methods.filter( + ( method ) => method.isConfigured + ).length; if ( currentMethod ) { return ( @@ -314,13 +201,12 @@ class Payments extends Component { { cloneElement( currentMethod.container, { query, installStep: this.getInstallStep(), + markConfigured: this.markConfigured, } ) } ); } - const methods = this.getMethodOptions(); - return (
{ methods.map( ( method ) => { @@ -328,6 +214,7 @@ class Payments extends Component { before, container, content, + isConfigured, key, title, visible, @@ -344,7 +231,7 @@ class Payments extends Component { >
{ key === this.recommendedMethod && - ! configured.includes( key ) && ( + ! isConfigured && (
{ __( @@ -365,7 +252,7 @@ class Payments extends Component {

- { container ? ( + { container && ! isConfigured ? ( ) : ( - + + this.toggleMethod( key ) + } + onClick={ ( e ) => e.stopPropagation() } + /> ) }
); } ) }
- { configured.length === 0 ? ( + { configuredMethods.length === 0 ? (