Refactor task tax to use promise chain (https://github.com/woocommerce/woocommerce-admin/pull/4683)
* Show success screen based on conditions instead of step * Use promise chain to handle updating tax settings * Fix up error handling for failed setting updates * Skip store location step if complete address exists * Fix up pending/requesting state logic * Allow opt in to TOS on tax task * Don't complete task from completeStep * Add caption styling to TOS text
This commit is contained in:
parent
1d5e7db33d
commit
8e5291e231
|
@ -696,11 +696,7 @@ BusinessDetails.contextType = CurrencyContext;
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withSelect( ( select ) => {
|
withSelect( ( select ) => {
|
||||||
const {
|
const { getSettings, getSettingsError } = select( SETTINGS_STORE_NAME );
|
||||||
getSettings,
|
|
||||||
getSettingsError,
|
|
||||||
isGetSettingsRequesting,
|
|
||||||
} = select( SETTINGS_STORE_NAME );
|
|
||||||
const { getProfileItems, getOnboardingError } = select(
|
const { getProfileItems, getOnboardingError } = select(
|
||||||
ONBOARDING_STORE_NAME
|
ONBOARDING_STORE_NAME
|
||||||
);
|
);
|
||||||
|
@ -716,7 +712,6 @@ export default compose(
|
||||||
isError: Boolean( getOnboardingError( 'updateProfileItems' ) ),
|
isError: Boolean( getOnboardingError( 'updateProfileItems' ) ),
|
||||||
profileItems: getProfileItems(),
|
profileItems: getProfileItems(),
|
||||||
isSettingsError: Boolean( getSettingsError( 'general' ) ),
|
isSettingsError: Boolean( getSettingsError( 'general' ) ),
|
||||||
isSettingsRequesting: isGetSettingsRequesting( 'general' ),
|
|
||||||
settings,
|
settings,
|
||||||
isInstallingActivating:
|
isInstallingActivating:
|
||||||
isPluginsRequesting( 'installPlugins' ) ||
|
isPluginsRequesting( 'installPlugins' ) ||
|
||||||
|
|
|
@ -237,11 +237,7 @@ StoreDetails.contextType = CurrencyContext;
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withSelect( ( select ) => {
|
withSelect( ( select ) => {
|
||||||
const {
|
const { getSettings, getSettingsError } = select( SETTINGS_STORE_NAME );
|
||||||
getSettings,
|
|
||||||
getSettingsError,
|
|
||||||
isGetSettingsRequesting,
|
|
||||||
} = select( SETTINGS_STORE_NAME );
|
|
||||||
const { getOnboardingError, getProfileItems } = select(
|
const { getOnboardingError, getProfileItems } = select(
|
||||||
ONBOARDING_STORE_NAME
|
ONBOARDING_STORE_NAME
|
||||||
);
|
);
|
||||||
|
@ -253,12 +249,10 @@ export default compose(
|
||||||
|
|
||||||
const { general: settings = {} } = getSettings( 'general' );
|
const { general: settings = {} } = getSettings( 'general' );
|
||||||
const isSettingsError = Boolean( getSettingsError( 'general' ) );
|
const isSettingsError = Boolean( getSettingsError( 'general' ) );
|
||||||
const isSettingsRequesting = isGetSettingsRequesting( 'general' );
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isProfileItemsError,
|
isProfileItemsError,
|
||||||
isSettingsError,
|
isSettingsError,
|
||||||
isSettingsRequesting,
|
|
||||||
profileItems,
|
profileItems,
|
||||||
settings,
|
settings,
|
||||||
};
|
};
|
||||||
|
|
|
@ -584,3 +584,8 @@
|
||||||
border-top-right-radius: 2px;
|
border-top-right-radius: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.woocommerce-task__caption {
|
||||||
|
color: $dark-gray-300;
|
||||||
|
margin-top: $gap;
|
||||||
|
}
|
||||||
|
|
|
@ -302,13 +302,13 @@ class Shipping extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isPending, step } = this.state;
|
const { isPending, step } = this.state;
|
||||||
const { isSettingsRequesting } = this.props;
|
const { isUpdateSettingsRequesting } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="woocommerce-task-shipping">
|
<div className="woocommerce-task-shipping">
|
||||||
<Card className="is-narrow">
|
<Card className="is-narrow">
|
||||||
<Stepper
|
<Stepper
|
||||||
isPending={ isPending || isSettingsRequesting }
|
isPending={ isPending || isUpdateSettingsRequesting }
|
||||||
isVertical
|
isVertical
|
||||||
currentStep={ step }
|
currentStep={ step }
|
||||||
steps={ this.getSteps() }
|
steps={ this.getSteps() }
|
||||||
|
@ -321,19 +321,14 @@ class Shipping extends Component {
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withSelect( ( select ) => {
|
withSelect( ( select ) => {
|
||||||
const {
|
const { getSettings, isUpdateSettingsRequesting } = select(
|
||||||
getSettings,
|
SETTINGS_STORE_NAME
|
||||||
getSettingsError,
|
);
|
||||||
isGetSettingsRequesting,
|
|
||||||
} = select( SETTINGS_STORE_NAME );
|
|
||||||
const { getActivePlugins, isJetpackConnected } = select(
|
const { getActivePlugins, isJetpackConnected } = select(
|
||||||
PLUGINS_STORE_NAME
|
PLUGINS_STORE_NAME
|
||||||
);
|
);
|
||||||
|
|
||||||
const { general: settings = {} } = getSettings( 'general' );
|
const { general: settings = {} } = getSettings( 'general' );
|
||||||
const isSettingsError = Boolean( getSettingsError( 'general' ) );
|
|
||||||
const isSettingsRequesting = isGetSettingsRequesting( 'general' );
|
|
||||||
|
|
||||||
const countryCode = getCountryCode(
|
const countryCode = getCountryCode(
|
||||||
settings.woocommerce_default_country
|
settings.woocommerce_default_country
|
||||||
);
|
);
|
||||||
|
@ -348,8 +343,7 @@ export default compose(
|
||||||
return {
|
return {
|
||||||
countryCode,
|
countryCode,
|
||||||
countryName,
|
countryName,
|
||||||
isSettingsError,
|
isUpdateSettingsRequesting: isUpdateSettingsRequesting( 'general' ),
|
||||||
isSettingsRequesting,
|
|
||||||
settings,
|
settings,
|
||||||
activePlugins,
|
activePlugins,
|
||||||
isJetpackConnected: isJetpackConnected(),
|
isJetpackConnected: isJetpackConnected(),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { Button } from '@wordpress/components';
|
import { Button, __experimentalText as Text } from '@wordpress/components';
|
||||||
import { Component, Fragment } from '@wordpress/element';
|
import { Component, Fragment } from '@wordpress/element';
|
||||||
import { compose } from '@wordpress/compose';
|
import { compose } from '@wordpress/compose';
|
||||||
import { difference, filter } from 'lodash';
|
import { difference, filter } from 'lodash';
|
||||||
|
@ -29,6 +29,7 @@ import {
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import Connect from 'dashboard/components/connect';
|
import Connect from 'dashboard/components/connect';
|
||||||
|
import { createNoticesFromResponse } from 'lib/notices';
|
||||||
import { getCountryCode } from 'dashboard/utils';
|
import { getCountryCode } from 'dashboard/utils';
|
||||||
import StoreLocation from './steps/location';
|
import StoreLocation from './steps/location';
|
||||||
import { recordEvent, queueRecordEvent } from 'lib/tracks';
|
import { recordEvent, queueRecordEvent } from 'lib/tracks';
|
||||||
|
@ -36,24 +37,18 @@ import { recordEvent, queueRecordEvent } from 'lib/tracks';
|
||||||
class Tax extends Component {
|
class Tax extends Component {
|
||||||
constructor( props ) {
|
constructor( props ) {
|
||||||
super( props );
|
super( props );
|
||||||
|
const { hasCompleteAddress, pluginsToActivate } = props;
|
||||||
|
|
||||||
this.initialState = {
|
this.initialState = {
|
||||||
isPending: false,
|
isPending: false,
|
||||||
stepIndex: 0,
|
stepIndex: hasCompleteAddress ? 1 : 0,
|
||||||
automatedTaxEnabled: true,
|
// Cache the value of pluginsToActivate so that we can
|
||||||
// Cache the value of pluginsToActivate so that we can show/hide tasks based on it, but not have them update mid task.
|
// show/hide tasks based on it, but not have them update mid task.
|
||||||
pluginsToActivate: props.pluginsToActivate,
|
cachedPluginsToActivate: pluginsToActivate,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.state = this.initialState;
|
this.state = this.initialState;
|
||||||
|
|
||||||
this.completeStep = this.completeStep.bind( this );
|
this.completeStep = this.completeStep.bind( this );
|
||||||
this.configureTaxRates = this.configureTaxRates.bind( this );
|
|
||||||
this.updateAutomatedTax = this.updateAutomatedTax.bind( this );
|
|
||||||
this.setIsPending = this.setIsPending.bind( this );
|
|
||||||
this.shouldShowSuccessScreen = this.shouldShowSuccessScreen.bind(
|
|
||||||
this
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -65,87 +60,22 @@ class Tax extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldShowSuccessScreen() {
|
shouldShowSuccessScreen() {
|
||||||
const { stepIndex } = this.state;
|
|
||||||
const {
|
const {
|
||||||
isJetpackConnected,
|
isJetpackConnected,
|
||||||
|
hasCompleteAddress,
|
||||||
pluginsToActivate,
|
pluginsToActivate,
|
||||||
generalSettings,
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {
|
|
||||||
woocommerce_store_address: storeAddress,
|
|
||||||
woocommerce_default_country: defaultCountry,
|
|
||||||
woocommerce_store_postcode: storePostCode,
|
|
||||||
} = generalSettings;
|
|
||||||
const isCompleteAddress = Boolean(
|
|
||||||
storeAddress && defaultCountry && storePostCode
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
stepIndex !== null &&
|
hasCompleteAddress &&
|
||||||
isCompleteAddress &&
|
|
||||||
! pluginsToActivate.length &&
|
! pluginsToActivate.length &&
|
||||||
isJetpackConnected &&
|
isJetpackConnected &&
|
||||||
this.isTaxJarSupported()
|
this.isTaxJarSupported()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate( prevProps ) {
|
|
||||||
const { generalSettings, isJetpackConnected, taxSettings } = this.props;
|
|
||||||
const {
|
|
||||||
woocommerce_calc_taxes: calcTaxes,
|
|
||||||
woocommerce_store_address: storeAddress,
|
|
||||||
woocommerce_default_country: defaultCountry,
|
|
||||||
woocommerce_store_postcode: storePostCode,
|
|
||||||
} = generalSettings;
|
|
||||||
const { stepIndex } = this.state;
|
|
||||||
const currentStep = this.getSteps()[ stepIndex ];
|
|
||||||
const currentStepKey = currentStep && currentStep.key;
|
|
||||||
|
|
||||||
if ( stepIndex !== null && this.shouldShowSuccessScreen() ) {
|
|
||||||
/* eslint-disable react/no-did-update-set-state */
|
|
||||||
this.setState( { stepIndex: null } );
|
|
||||||
/* eslint-enable react/no-did-update-set-state */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
taxSettings.wc_connect_taxes_enabled &&
|
|
||||||
taxSettings.wc_connect_taxes_enabled !==
|
|
||||||
prevProps.taxSettings.wc_connect_taxes_enabled
|
|
||||||
) {
|
|
||||||
/* eslint-disable react/no-did-update-set-state */
|
|
||||||
this.setState( {
|
|
||||||
automatedTaxEnabled:
|
|
||||||
taxSettings.wc_connect_taxes_enabled === 'yes'
|
|
||||||
? true
|
|
||||||
: false,
|
|
||||||
} );
|
|
||||||
/* eslint-enable react/no-did-update-set-state */
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currentStepKey === 'connect' && isJetpackConnected ) {
|
|
||||||
this.completeStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
const isCompleteAddress = Boolean(
|
|
||||||
storeAddress && defaultCountry && storePostCode
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( currentStepKey === 'store_location' && isCompleteAddress ) {
|
|
||||||
this.completeStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
woocommerce_calc_taxes: prevCalcTaxes,
|
|
||||||
} = prevProps.generalSettings;
|
|
||||||
if ( prevCalcTaxes === 'no' && calcTaxes === 'yes' ) {
|
|
||||||
window.location = getAdminLink(
|
|
||||||
'admin.php?page=wc-settings&tab=tax§ion=standard'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isTaxJarSupported() {
|
isTaxJarSupported() {
|
||||||
const { countryCode, tosAccepted } = this.props;
|
const { countryCode } = this.props;
|
||||||
const {
|
const {
|
||||||
automatedTaxSupportedCountries = [],
|
automatedTaxSupportedCountries = [],
|
||||||
taxJarActivated,
|
taxJarActivated,
|
||||||
|
@ -153,7 +83,6 @@ class Tax extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
! taxJarActivated && // WCS integration doesn't work with the official TaxJar plugin.
|
! taxJarActivated && // WCS integration doesn't work with the official TaxJar plugin.
|
||||||
tosAccepted &&
|
|
||||||
automatedTaxSupportedCountries.includes( countryCode )
|
automatedTaxSupportedCountries.includes( countryCode )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -165,12 +94,10 @@ class Tax extends Component {
|
||||||
|
|
||||||
if ( nextStep ) {
|
if ( nextStep ) {
|
||||||
this.setState( { stepIndex: stepIndex + 1 } );
|
this.setState( { stepIndex: stepIndex + 1 } );
|
||||||
} else {
|
|
||||||
getHistory().push( getNewPath( {}, '/', {} ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async configureTaxRates() {
|
async manuallyConfigureTaxRates() {
|
||||||
const {
|
const {
|
||||||
generalSettings,
|
generalSettings,
|
||||||
updateAndPersistSettingsForGroup,
|
updateAndPersistSettingsForGroup,
|
||||||
|
@ -178,82 +105,87 @@ class Tax extends Component {
|
||||||
|
|
||||||
if ( generalSettings.woocommerce_calc_taxes !== 'yes' ) {
|
if ( generalSettings.woocommerce_calc_taxes !== 'yes' ) {
|
||||||
this.setState( { isPending: true } );
|
this.setState( { isPending: true } );
|
||||||
await updateAndPersistSettingsForGroup( 'general', {
|
updateAndPersistSettingsForGroup( 'general', {
|
||||||
general: {
|
general: {
|
||||||
...generalSettings,
|
...generalSettings,
|
||||||
woocommerce_calc_taxes: 'yes',
|
woocommerce_calc_taxes: 'yes',
|
||||||
},
|
},
|
||||||
} );
|
} )
|
||||||
|
.then( () => this.redirectToTaxSettings() )
|
||||||
|
.catch( ( error ) => createNoticesFromResponse( error ) );
|
||||||
|
} else {
|
||||||
|
this.redirectToTaxSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.location = getAdminLink(
|
|
||||||
'admin.php?page=wc-settings&tab=tax§ion=standard&wc_onboarding_active_task=tax'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateAutomatedTax() {
|
updateAutomatedTax( isEnabling ) {
|
||||||
const {
|
const {
|
||||||
createNotice,
|
createNotice,
|
||||||
updateAndPersistSettingsForGroup,
|
updateAndPersistSettingsForGroup,
|
||||||
generalSettings,
|
generalSettings,
|
||||||
taxSettings,
|
taxSettings,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { automatedTaxEnabled } = this.state;
|
|
||||||
|
|
||||||
await updateAndPersistSettingsForGroup( 'tax', {
|
Promise.all( [
|
||||||
tax: {
|
updateAndPersistSettingsForGroup( 'tax', {
|
||||||
...taxSettings,
|
tax: {
|
||||||
wc_connect_taxes_enabled: automatedTaxEnabled ? 'yes' : 'no',
|
...taxSettings,
|
||||||
},
|
wc_connect_taxes_enabled: isEnabling ? 'yes' : 'no',
|
||||||
} );
|
},
|
||||||
|
} ),
|
||||||
await updateAndPersistSettingsForGroup( 'general', {
|
updateAndPersistSettingsForGroup( 'general', {
|
||||||
general: {
|
general: {
|
||||||
...generalSettings,
|
...generalSettings,
|
||||||
woocommerce_calc_taxes: 'yes',
|
woocommerce_calc_taxes: 'yes',
|
||||||
},
|
},
|
||||||
} );
|
} ),
|
||||||
|
] )
|
||||||
if (
|
.then( () => {
|
||||||
! this.props.isTaxSettingsError &&
|
// @todo This is a workaround to force the task to mark as complete.
|
||||||
! this.props.isGeneralSettingsError
|
// This should probably be updated to use wc-api so we can fetch tax rates.
|
||||||
) {
|
setSetting( 'onboarding', {
|
||||||
// @todo This is a workaround to force the task to mark as complete.
|
...getSetting( 'onboarding', {} ),
|
||||||
// This should probably be updated to use wc-api so we can fetch tax rates.
|
isTaxComplete: true,
|
||||||
setSetting( 'onboarding', {
|
} );
|
||||||
...getSetting( 'onboarding', {} ),
|
if ( isEnabling ) {
|
||||||
isTaxComplete: true,
|
createNotice(
|
||||||
|
'success',
|
||||||
|
__(
|
||||||
|
"You're awesome! One less item on your to-do list ✅",
|
||||||
|
'woocommerce-admin'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
getHistory().push( getNewPath( {}, '/', {} ) );
|
||||||
|
} else {
|
||||||
|
this.redirectToTaxSettings();
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
.catch( () => {
|
||||||
|
createNotice(
|
||||||
|
'error',
|
||||||
|
__(
|
||||||
|
'There was a problem updating your tax settings.',
|
||||||
|
'woocommerce-admin'
|
||||||
|
)
|
||||||
|
);
|
||||||
} );
|
} );
|
||||||
createNotice(
|
|
||||||
'success',
|
|
||||||
__(
|
|
||||||
"You're awesome! One less item on your to-do list ✅",
|
|
||||||
'woocommerce-admin'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if ( automatedTaxEnabled ) {
|
|
||||||
getHistory().push( getNewPath( {}, '/', {} ) );
|
|
||||||
} else {
|
|
||||||
this.configureTaxRates();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
createNotice(
|
|
||||||
'error',
|
|
||||||
__(
|
|
||||||
'There was a problem updating your tax settings.',
|
|
||||||
'woocommerce-admin'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsPending( value ) {
|
redirectToTaxSettings() {
|
||||||
this.setState( { isPending: value } );
|
window.location = getAdminLink(
|
||||||
|
'admin.php?page=wc-settings&tab=tax§ion=standard&wc_onboarding_active_task=tax'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSteps() {
|
getSteps() {
|
||||||
const { generalSettings, isJetpackConnected } = this.props;
|
const {
|
||||||
const { isPending, pluginsToActivate } = this.state;
|
generalSettings,
|
||||||
|
isJetpackConnected,
|
||||||
|
isPending,
|
||||||
|
tosAccepted,
|
||||||
|
updateOptions,
|
||||||
|
} = this.props;
|
||||||
|
const { cachedPluginsToActivate } = this.state;
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
|
@ -273,12 +205,7 @@ class Tax extends Component {
|
||||||
recordEvent( 'tasklist_tax_set_location', {
|
recordEvent( 'tasklist_tax_set_location', {
|
||||||
country,
|
country,
|
||||||
} );
|
} );
|
||||||
if ( this.shouldShowSuccessScreen() ) {
|
this.completeStep();
|
||||||
this.setState( { stepIndex: null } );
|
|
||||||
// Only complete step if another update hasn't already shown succes screen.
|
|
||||||
} else if ( this.state.stepIndex !== null ) {
|
|
||||||
this.completeStep();
|
|
||||||
}
|
|
||||||
} }
|
} }
|
||||||
isSettingsRequesting={ false }
|
isSettingsRequesting={ false }
|
||||||
settings={ generalSettings }
|
settings={ generalSettings }
|
||||||
|
@ -297,31 +224,63 @@ class Tax extends Component {
|
||||||
'woocommerce-admin'
|
'woocommerce-admin'
|
||||||
),
|
),
|
||||||
content: (
|
content: (
|
||||||
<Plugins
|
<Fragment>
|
||||||
onComplete={ () => {
|
<Plugins
|
||||||
recordEvent( 'tasklist_tax_install_extensions', {
|
onComplete={ () => {
|
||||||
install_extensions: true,
|
recordEvent(
|
||||||
} );
|
'tasklist_tax_install_extensions',
|
||||||
this.completeStep();
|
{
|
||||||
} }
|
install_extensions: true,
|
||||||
onSkip={ () => {
|
}
|
||||||
queueRecordEvent(
|
);
|
||||||
'tasklist_tax_install_extensions',
|
updateOptions( {
|
||||||
{
|
woocommerce_setup_jetpack_opted_in: true,
|
||||||
install_extensions: false,
|
} );
|
||||||
}
|
this.completeStep();
|
||||||
);
|
} }
|
||||||
window.location.href = getAdminLink(
|
onSkip={ () => {
|
||||||
'admin.php?page=wc-settings&tab=tax§ion=standard'
|
queueRecordEvent(
|
||||||
);
|
'tasklist_tax_install_extensions',
|
||||||
} }
|
{
|
||||||
skipText={ __(
|
install_extensions: false,
|
||||||
'Set up tax rates manually',
|
}
|
||||||
'woocommerce-admin'
|
);
|
||||||
|
this.redirectToTaxSettings();
|
||||||
|
} }
|
||||||
|
skipText={ __(
|
||||||
|
'Set up tax rates manually',
|
||||||
|
'woocommerce-admin'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
{ ! tosAccepted && (
|
||||||
|
<Text
|
||||||
|
variant="caption"
|
||||||
|
className="woocommerce-task__caption"
|
||||||
|
>
|
||||||
|
{ interpolateComponents( {
|
||||||
|
mixedString: __(
|
||||||
|
'By installing Jetpack and WooCommerce Services you agree to the {{link}}Terms of Service{{/link}}.',
|
||||||
|
'woocommerce-admin'
|
||||||
|
),
|
||||||
|
components: {
|
||||||
|
link: (
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
'https://wordpress.com/tos/'
|
||||||
|
}
|
||||||
|
target="_blank"
|
||||||
|
type="external"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
} ) }
|
||||||
|
</Text>
|
||||||
) }
|
) }
|
||||||
/>
|
</Fragment>
|
||||||
),
|
),
|
||||||
visible: pluginsToActivate.length && this.isTaxJarSupported(),
|
visible:
|
||||||
|
( cachedPluginsToActivate.length || ! tosAccepted ) &&
|
||||||
|
this.isTaxJarSupported(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'connect',
|
key: 'connect',
|
||||||
|
@ -333,7 +292,6 @@ class Tax extends Component {
|
||||||
content: (
|
content: (
|
||||||
<Connect
|
<Connect
|
||||||
{ ...this.props }
|
{ ...this.props }
|
||||||
setIsPending={ this.setIsPending }
|
|
||||||
onConnect={ () => {
|
onConnect={ () => {
|
||||||
recordEvent( 'tasklist_tax_connect_store', {
|
recordEvent( 'tasklist_tax_connect_store', {
|
||||||
connect: true,
|
connect: true,
|
||||||
|
@ -343,9 +301,7 @@ class Tax extends Component {
|
||||||
queueRecordEvent( 'tasklist_tax_connect_store', {
|
queueRecordEvent( 'tasklist_tax_connect_store', {
|
||||||
connect: false,
|
connect: false,
|
||||||
} );
|
} );
|
||||||
window.location.href = getAdminLink(
|
this.manuallyConfigureTaxRates();
|
||||||
'admin.php?page=wc-settings&tab=tax§ion=standard'
|
|
||||||
);
|
|
||||||
} }
|
} }
|
||||||
skipText={ __(
|
skipText={ __(
|
||||||
'Set up tax rates manually',
|
'Set up tax rates manually',
|
||||||
|
@ -365,11 +321,12 @@ class Tax extends Component {
|
||||||
content: (
|
content: (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={ isPending }
|
||||||
isPrimary
|
isPrimary
|
||||||
isBusy={ isPending }
|
isBusy={ isPending }
|
||||||
onClick={ () => {
|
onClick={ () => {
|
||||||
recordEvent( 'tasklist_tax_config_rates' );
|
recordEvent( 'tasklist_tax_config_rates' );
|
||||||
this.configureTaxRates();
|
this.manuallyConfigureTaxRates();
|
||||||
} }
|
} }
|
||||||
>
|
>
|
||||||
{ __( 'Configure', 'woocommerce-admin' ) }
|
{ __( 'Configure', 'woocommerce-admin' ) }
|
||||||
|
@ -405,21 +362,14 @@ class Tax extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isPending, stepIndex } = this.state;
|
const { stepIndex } = this.state;
|
||||||
const { isTaxSettingsRequesting, taxSettings } = this.props;
|
const { isPending, isResolving } = this.props;
|
||||||
const step = this.getSteps()[ stepIndex ];
|
const step = this.getSteps()[ stepIndex ];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="woocommerce-task-tax">
|
<div className="woocommerce-task-tax">
|
||||||
<Card className="is-narrow">
|
<Card className="is-narrow">
|
||||||
{ step ? (
|
{ this.shouldShowSuccessScreen() ? (
|
||||||
<Stepper
|
|
||||||
isPending={ isPending || isTaxSettingsRequesting }
|
|
||||||
isVertical={ true }
|
|
||||||
currentStep={ step.key }
|
|
||||||
steps={ this.getSteps() }
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="woocommerce-task-tax__success">
|
<div className="woocommerce-task-tax__success">
|
||||||
<span
|
<span
|
||||||
className="woocommerce-task-tax__success-icon"
|
className="woocommerce-task-tax__success-icon"
|
||||||
|
@ -444,11 +394,9 @@ class Tax extends Component {
|
||||||
} ) }
|
} ) }
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={ isPending }
|
||||||
isPrimary
|
isPrimary
|
||||||
isBusy={
|
isBusy={ isPending }
|
||||||
Object.keys( taxSettings ).length &&
|
|
||||||
isTaxSettingsRequesting
|
|
||||||
}
|
|
||||||
onClick={ () => {
|
onClick={ () => {
|
||||||
recordEvent(
|
recordEvent(
|
||||||
'tasklist_tax_setup_automated_proceed',
|
'tasklist_tax_setup_automated_proceed',
|
||||||
|
@ -456,15 +404,14 @@ class Tax extends Component {
|
||||||
setup_automatically: true,
|
setup_automatically: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.setState(
|
this.updateAutomatedTax( true );
|
||||||
{ automatedTaxEnabled: true },
|
|
||||||
this.updateAutomatedTax
|
|
||||||
);
|
|
||||||
} }
|
} }
|
||||||
>
|
>
|
||||||
{ __( 'Yes please', 'woocommerce-admin' ) }
|
{ __( 'Yes please', 'woocommerce-admin' ) }
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={ isPending }
|
||||||
|
isBusy={ isPending }
|
||||||
onClick={ () => {
|
onClick={ () => {
|
||||||
recordEvent(
|
recordEvent(
|
||||||
'tasklist_tax_setup_automated_proceed',
|
'tasklist_tax_setup_automated_proceed',
|
||||||
|
@ -472,10 +419,7 @@ class Tax extends Component {
|
||||||
setup_automatically: false,
|
setup_automatically: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.setState(
|
this.updateAutomatedTax( false );
|
||||||
{ automatedTaxEnabled: false },
|
|
||||||
this.updateAutomatedTax
|
|
||||||
);
|
|
||||||
} }
|
} }
|
||||||
>
|
>
|
||||||
{ __(
|
{ __(
|
||||||
|
@ -484,6 +428,13 @@ class Tax extends Component {
|
||||||
) }
|
) }
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<Stepper
|
||||||
|
isPending={ isPending || isResolving }
|
||||||
|
isVertical={ true }
|
||||||
|
currentStep={ step.key }
|
||||||
|
steps={ this.getSteps() }
|
||||||
|
/>
|
||||||
) }
|
) }
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -493,26 +444,30 @@ class Tax extends Component {
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withSelect( ( select ) => {
|
withSelect( ( select ) => {
|
||||||
const {
|
const { getSettings, isUpdateSettingsRequesting } = select(
|
||||||
getSettings,
|
SETTINGS_STORE_NAME
|
||||||
getSettingsError,
|
|
||||||
isGetSettingsRequesting,
|
|
||||||
} = select( SETTINGS_STORE_NAME );
|
|
||||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
|
||||||
const { getActivePlugins, isJetpackConnected } = select(
|
|
||||||
PLUGINS_STORE_NAME
|
|
||||||
);
|
);
|
||||||
|
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||||
|
const {
|
||||||
|
getActivePlugins,
|
||||||
|
isJetpackConnected,
|
||||||
|
isPluginsRequesting,
|
||||||
|
} = select( PLUGINS_STORE_NAME );
|
||||||
|
|
||||||
const { general: generalSettings = {} } = getSettings( 'general' );
|
const { general: generalSettings = {} } = getSettings( 'general' );
|
||||||
const isGeneralSettingsError = Boolean( getSettingsError( 'general' ) );
|
|
||||||
const countryCode = getCountryCode(
|
const countryCode = getCountryCode(
|
||||||
generalSettings.woocommerce_default_country
|
generalSettings.woocommerce_default_country
|
||||||
);
|
);
|
||||||
|
const {
|
||||||
|
woocommerce_store_address: storeAddress,
|
||||||
|
woocommerce_default_country: defaultCountry,
|
||||||
|
woocommerce_store_postcode: storePostCode,
|
||||||
|
} = generalSettings;
|
||||||
|
const hasCompleteAddress = Boolean(
|
||||||
|
storeAddress && defaultCountry && storePostCode
|
||||||
|
);
|
||||||
|
|
||||||
const { tax: taxSettings = {} } = getSettings( 'tax' );
|
const { tax: taxSettings = {} } = getSettings( 'tax' );
|
||||||
const isTaxSettingsError = Boolean( getSettingsError( 'tax' ) );
|
|
||||||
const isTaxSettingsRequesting = isGetSettingsRequesting( 'tax' );
|
|
||||||
|
|
||||||
const activePlugins = getActivePlugins();
|
const activePlugins = getActivePlugins();
|
||||||
const pluginsToActivate = difference(
|
const pluginsToActivate = difference(
|
||||||
[ 'jetpack', 'woocommerce-services' ],
|
[ 'jetpack', 'woocommerce-services' ],
|
||||||
|
@ -523,20 +478,26 @@ export default compose(
|
||||||
connectOptions.tos_accepted ||
|
connectOptions.tos_accepted ||
|
||||||
getOption( 'woocommerce_setup_jetpack_opted_in' );
|
getOption( 'woocommerce_setup_jetpack_opted_in' );
|
||||||
|
|
||||||
|
const isPending =
|
||||||
|
isUpdateSettingsRequesting( 'tax' ) ||
|
||||||
|
isUpdateSettingsRequesting( 'general' );
|
||||||
|
const isResolving = isPluginsRequesting( 'getJetpackConnectUrl' );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isGeneralSettingsError,
|
|
||||||
generalSettings,
|
|
||||||
countryCode,
|
countryCode,
|
||||||
taxSettings,
|
generalSettings,
|
||||||
isTaxSettingsError,
|
hasCompleteAddress,
|
||||||
isTaxSettingsRequesting,
|
|
||||||
isJetpackConnected: isJetpackConnected(),
|
isJetpackConnected: isJetpackConnected(),
|
||||||
|
isPending,
|
||||||
|
isResolving,
|
||||||
pluginsToActivate,
|
pluginsToActivate,
|
||||||
|
taxSettings,
|
||||||
tosAccepted,
|
tosAccepted,
|
||||||
};
|
};
|
||||||
} ),
|
} ),
|
||||||
withDispatch( ( dispatch ) => {
|
withDispatch( ( dispatch ) => {
|
||||||
const { createNotice } = dispatch( 'core/notices' );
|
const { createNotice } = dispatch( 'core/notices' );
|
||||||
|
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||||
const { updateAndPersistSettingsForGroup } = dispatch(
|
const { updateAndPersistSettingsForGroup } = dispatch(
|
||||||
SETTINGS_STORE_NAME
|
SETTINGS_STORE_NAME
|
||||||
);
|
);
|
||||||
|
@ -544,6 +505,7 @@ export default compose(
|
||||||
return {
|
return {
|
||||||
createNotice,
|
createNotice,
|
||||||
updateAndPersistSettingsForGroup,
|
updateAndPersistSettingsForGroup,
|
||||||
|
updateOptions,
|
||||||
};
|
};
|
||||||
} )
|
} )
|
||||||
)( Tax );
|
)( Tax );
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* External Dependencies
|
* External Dependencies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
import { apiFetch, select } from '@wordpress/data-controls';
|
import { apiFetch, select } from '@wordpress/data-controls';
|
||||||
import { concat } from 'lodash';
|
import { concat } from 'lodash';
|
||||||
|
|
||||||
|
@ -65,11 +66,16 @@ export function* persistSettingsForGroup( group ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get data slice for keys
|
// get data slice for keys
|
||||||
const dirtyData = yield select( STORE_NAME, 'getSettingsForGroup', group, dirtyKeys );
|
const dirtyData = yield select(
|
||||||
|
STORE_NAME,
|
||||||
|
'getSettingsForGroup',
|
||||||
|
group,
|
||||||
|
dirtyKeys
|
||||||
|
);
|
||||||
const url = `${ NAMESPACE }/settings/${ group }/batch`;
|
const url = `${ NAMESPACE }/settings/${ group }/batch`;
|
||||||
|
|
||||||
const update = dirtyKeys.reduce( ( updates, key ) => {
|
const update = dirtyKeys.reduce( ( updates, key ) => {
|
||||||
const u = Object.keys( dirtyData[ key ] ).map( k => {
|
const u = Object.keys( dirtyData[ key ] ).map( ( k ) => {
|
||||||
return { id: k, value: dirtyData[ key ][ k ] };
|
return { id: k, value: dirtyData[ key ][ k ] };
|
||||||
} );
|
} );
|
||||||
return concat( updates, u );
|
return concat( updates, u );
|
||||||
|
@ -80,16 +86,25 @@ export function* persistSettingsForGroup( group ) {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: { update },
|
data: { update },
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
yield setIsRequesting( group, false );
|
||||||
|
|
||||||
if ( ! results ) {
|
if ( ! results ) {
|
||||||
throw new Error( 'settings did not update' );
|
throw new Error(
|
||||||
|
__(
|
||||||
|
'There was a problem updating your settings.',
|
||||||
|
'woocommerce-admin'
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove dirtyKeys from map - note we're only doing this if there is no error.
|
// remove dirtyKeys from map - note we're only doing this if there is no error.
|
||||||
yield clearIsDirty( group );
|
yield clearIsDirty( group );
|
||||||
} catch ( e ) {
|
} catch ( e ) {
|
||||||
yield updateErrorForGroup( group, null, e );
|
yield updateErrorForGroup( group, null, e );
|
||||||
|
yield setIsRequesting( group, false );
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
// finally set the persisting state
|
|
||||||
yield setIsRequesting( group, false );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearSettings() {
|
export function clearSettings() {
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
*/
|
*/
|
||||||
import { getResourceName, getResourcePrefix } from '../utils';
|
import { getResourceName, getResourcePrefix } from '../utils';
|
||||||
|
|
||||||
export const getSettingsGroupNames = state => {
|
export const getSettingsGroupNames = ( state ) => {
|
||||||
const groupNames = new Set(
|
const groupNames = new Set(
|
||||||
Object.keys( state ).map( resourceName => {
|
Object.keys( state ).map( ( resourceName ) => {
|
||||||
return getResourcePrefix( resourceName );
|
return getResourcePrefix( resourceName );
|
||||||
} )
|
} )
|
||||||
);
|
);
|
||||||
|
@ -14,11 +14,11 @@ export const getSettingsGroupNames = state => {
|
||||||
|
|
||||||
export const getSettings = ( state, group ) => {
|
export const getSettings = ( state, group ) => {
|
||||||
const settings = {};
|
const settings = {};
|
||||||
const settingIds = state[ group ] && state[ group ].data || [];
|
const settingIds = ( state[ group ] && state[ group ].data ) || [];
|
||||||
if ( settingIds.length === 0 ) {
|
if ( settingIds.length === 0 ) {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
settingIds.forEach( id => {
|
settingIds.forEach( ( id ) => {
|
||||||
settings[ id ] = state[ getResourceName( group, id ) ].data;
|
settings[ id ] = state[ getResourceName( group, id ) ].data;
|
||||||
} );
|
} );
|
||||||
return settings;
|
return settings;
|
||||||
|
@ -47,7 +47,7 @@ export const getSettingsForGroup = ( state, group, keys ) => {
|
||||||
}, {} );
|
}, {} );
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isGetSettingsRequesting = ( state, group ) => {
|
export const isUpdateSettingsRequesting = ( state, group ) => {
|
||||||
return state[ group ] && Boolean( state[ group ].isRequesting );
|
return state[ group ] && Boolean( state[ group ].isRequesting );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,9 +70,16 @@ export const isGetSettingsRequesting = ( state, group ) => {
|
||||||
* @return {*} The value present in the settings state for the given
|
* @return {*} The value present in the settings state for the given
|
||||||
* name.
|
* name.
|
||||||
*/
|
*/
|
||||||
export function getSetting( state, group, name, fallback = false, filter = val => val ) {
|
export function getSetting(
|
||||||
|
state,
|
||||||
|
group,
|
||||||
|
name,
|
||||||
|
fallback = false,
|
||||||
|
filter = ( val ) => val
|
||||||
|
) {
|
||||||
const resourceName = getResourceName( group, name );
|
const resourceName = getResourceName( group, name );
|
||||||
const value = ( state[ resourceName ] && state[ resourceName ].data ) || fallback;
|
const value =
|
||||||
|
( state[ resourceName ] && state[ resourceName ].data ) || fallback;
|
||||||
return filter( value, fallback );
|
return filter( value, fallback );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +93,7 @@ export const getLastSettingsErrorForGroup = ( state, group ) => {
|
||||||
|
|
||||||
export const getSettingsError = ( state, group, id ) => {
|
export const getSettingsError = ( state, group, id ) => {
|
||||||
if ( ! id ) {
|
if ( ! id ) {
|
||||||
return state[ group ] && state[ group ].error || false;
|
return ( state[ group ] && state[ group ].error ) || false;
|
||||||
}
|
}
|
||||||
return state[ getResourceName( group, id ) ].error || false;
|
return state[ getResourceName( group, id ) ].error || false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
@ -7,18 +6,23 @@ import { STORE_NAME } from './constants';
|
||||||
import { useCallback } from '@wordpress/element';
|
import { useCallback } from '@wordpress/element';
|
||||||
|
|
||||||
export const useSettings = ( group, settingsKeys = [] ) => {
|
export const useSettings = ( group, settingsKeys = [] ) => {
|
||||||
const { requestedSettings, settingsError, isRequesting, isDirty } = useSelect(
|
const {
|
||||||
select => {
|
requestedSettings,
|
||||||
|
settingsError,
|
||||||
|
isRequesting,
|
||||||
|
isDirty,
|
||||||
|
} = useSelect(
|
||||||
|
( select ) => {
|
||||||
const {
|
const {
|
||||||
getLastSettingsErrorForGroup,
|
getLastSettingsErrorForGroup,
|
||||||
getSettingsForGroup,
|
getSettingsForGroup,
|
||||||
getIsDirty,
|
getIsDirty,
|
||||||
isGetSettingsRequesting,
|
isUpdateSettingsRequesting,
|
||||||
} = select( STORE_NAME );
|
} = select( STORE_NAME );
|
||||||
return {
|
return {
|
||||||
requestedSettings: getSettingsForGroup( group, settingsKeys ),
|
requestedSettings: getSettingsForGroup( group, settingsKeys ),
|
||||||
settingsError: Boolean( getLastSettingsErrorForGroup( group ) ),
|
settingsError: Boolean( getLastSettingsErrorForGroup( group ) ),
|
||||||
isRequesting: isGetSettingsRequesting( group ),
|
isRequesting: isUpdateSettingsRequesting( group ),
|
||||||
isDirty: getIsDirty( group, settingsKeys ),
|
isDirty: getIsDirty( group, settingsKeys ),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -35,14 +39,11 @@ export const useSettings = ( group, settingsKeys = [] ) => {
|
||||||
},
|
},
|
||||||
[ group ]
|
[ group ]
|
||||||
);
|
);
|
||||||
const persistSettings = useCallback(
|
const persistSettings = useCallback( () => {
|
||||||
() => {
|
// this action would simply persist all settings marked as dirty in the
|
||||||
// this action would simply persist all settings marked as dirty in the
|
// store state and then remove the dirty record in the isDirtyMap
|
||||||
// store state and then remove the dirty record in the isDirtyMap
|
persistSettingsForGroup( group );
|
||||||
persistSettingsForGroup( group );
|
}, [ group ] );
|
||||||
},
|
|
||||||
[ group ]
|
|
||||||
);
|
|
||||||
const updateAndPersistSettings = useCallback(
|
const updateAndPersistSettings = useCallback(
|
||||||
( name, data ) => {
|
( name, data ) => {
|
||||||
updateAndPersistSettingsForGroup( group, { [ name ]: data } );
|
updateAndPersistSettingsForGroup( group, { [ name ]: data } );
|
||||||
|
|
Loading…
Reference in New Issue