Add country validation to subscription inclusion (https://github.com/woocommerce/woocommerce-admin/pull/7777)
* Add country validation * Add OnboardingProductTypes * Add OnboardingProductTypes * Add country validation to product task * Add `productTypes` data handling * Add country validation and new productTypes handling * Fix to get `productTypes` from a SSOT * Add `invalidateResolution` for `getTaskLists` * Fixed testing instructions * Fix `isTaskListHidden` issue * Fixed product type * Added constant `EMPTY_ARRAY` to `selectors.ts` * Fixed constant `EMPTY_ARRAY` * Moved `invalidateResolutionForStoreSelector` into OBW * Updated testing instructions * Updated testing instructions * Fixed testing instructions Co-authored-by: Fernando Marichal <contacto@fernandomarichal.com>
This commit is contained in:
parent
a8a3238c38
commit
f20113fa01
|
@ -1,27 +1,26 @@
|
||||||
# Testing instructions
|
# Testing instructions
|
||||||
|
|
||||||
## Unreleased
|
|
||||||
|
|
||||||
## 2.8.0
|
## 2.8.0
|
||||||
|
|
||||||
### Store Profiler and Product task - include Subscriptions #7734
|
### Store Profiler and Product task - include Subscriptions #7734
|
||||||
|
|
||||||
##### Feature: turned off
|
##### Non US stores
|
||||||
|
|
||||||
1. Deactivate and delete `WooCommerce Payments` if you have it installed.
|
1. Deactivate and delete `WooCommerce Payments` if you have it installed.
|
||||||
2. Go to the 3rd step of the store profiler (`Product Types`).
|
2. Go to step one of the store profiler and select `France` (or any country other than the US) as the store `Country / Region`.
|
||||||
3. Verify `Subscriptions` is shown as a paid extension (with a price chip).
|
3. Go to step three of the store profiler (`Product Types`).
|
||||||
4. Check `Subscriptions` and continue with the OBW.
|
4. Verify `Subscriptions` is shown as a paid extension (with a price chip).
|
||||||
5. Go back to the `Home` screen. Check that the task item `Add Subscriptions to my store` is visible in the setup task list.
|
5. Check `Subscriptions` and continue with the OBW.
|
||||||
6. Press `Add my products` in the setup task list.
|
6. Go back to the `Home` screen by pressing `Skip setup store details` in step one of the store profiler. Check that the task item `Add Subscriptions to my store` is visible in the setup task list.
|
||||||
7. Select `Start with a template`. Verify that the option `Subscription product` is not visible in the popup.
|
7. Press `Add my products` in the setup task list.
|
||||||
|
8. Select `Start with a template`. Verify that the option `Subscription product` is not visible in the popup.
|
||||||
|
|
||||||
##### Feature: turned on
|
##### US stores
|
||||||
|
|
||||||
1. Install and activate this plugin to turn on the subscriptions inclusion -> https://gist.github.com/octaedro/455eb4c85887608c253249bad533ccb3
|
9. Deactivate and delete `WooCommerce Payments`.
|
||||||
2. Deactivate and delete `WooCommerce Payments` if you have it installed.
|
10. Go to step one of the store profiler and select `US` as the store `Country / Region`.
|
||||||
3. Go to the 3rd step of the store profiler (`Product Types`).
|
11. Go to step three of the store profiler (`Product Types`).
|
||||||
4. Verify `Subscriptions` is shown as free (without a price chip). Also, verify that the text
|
12. Verify `Subscriptions` is shown as free (without a price chip). Also, verify that the text
|
||||||
|
|
||||||
```
|
```
|
||||||
The following extensions will be added to your site for free: WooCommerce Payments. An account is required to use this feature
|
The following extensions will be added to your site for free: WooCommerce Payments. An account is required to use this feature
|
||||||
|
@ -31,20 +30,23 @@ is visible at the bottom when `WooCommerce Payments` is not installed.
|
||||||
|
|
||||||
![screenshot-one wordpress test-2021 09 30-14_12_58](https://user-images.githubusercontent.com/1314156/135506696-b7812f7e-437f-4d89-956a-b73248f70f6b.png)
|
![screenshot-one wordpress test-2021 09 30-14_12_58](https://user-images.githubusercontent.com/1314156/135506696-b7812f7e-437f-4d89-956a-b73248f70f6b.png)
|
||||||
|
|
||||||
5. Press `Continue` and verify that the `WooCommerce Payments` plugin is installed and activated and it's not shown in the `Free features` list
|
|
||||||
|
13. Check `Subscriptions` and press `Continue` and verify that the `WooCommerce Payments` plugin is installed and activated and it's not shown in the `Free features` list
|
||||||
|
|
||||||
![screenshot-one wordpress test-2021 09 30-14_32_20](https://user-images.githubusercontent.com/1314156/135506727-d8888f2b-3424-4cf5-a4bf-b67a14a198b6.png)
|
![screenshot-one wordpress test-2021 09 30-14_32_20](https://user-images.githubusercontent.com/1314156/135506727-d8888f2b-3424-4cf5-a4bf-b67a14a198b6.png)
|
||||||
|
|
||||||
6. Go back to the `Home` screen. Check that the task item `Add Subscriptions to my store` is not visible in the setup task list.
|
14. Verify that the `WooCommerce Payments` plugin is being shown in the `Free features` list when the store country is other than the `US`.
|
||||||
|
|
||||||
|
15. Go back to the `Home` screen by pressing `Skip setup store details` in step one of the store profiler. Check that the task item `Add Subscriptions to my store` is not visible in the setup task list. It should be visible if the store is from any country other than the `US`.
|
||||||
|
|
||||||
![screenshot-one wordpress test-2021 09 30-14_39_28](https://user-images.githubusercontent.com/1314156/135506770-91571f8f-2e2e-43a7-b092-b9e5fdf56df8.png)
|
![screenshot-one wordpress test-2021 09 30-14_39_28](https://user-images.githubusercontent.com/1314156/135506770-91571f8f-2e2e-43a7-b092-b9e5fdf56df8.png)
|
||||||
|
|
||||||
7. Press `Add my products` in the setup task list.
|
16. Press `Add my products` in the setup task list.
|
||||||
8. Select `Start with a template`. Verify that the option `Subscription product` is visible in the popup
|
17. Select `Start with a template`. Verify that the option `Subscription product` is visible in the popup
|
||||||
|
|
||||||
![screenshot-one wordpress test-2021 09 30-14_35_22](https://user-images.githubusercontent.com/1314156/135506748-0b7bdce5-b006-47f9-9289-03ed26e4950c.png)
|
![screenshot-one wordpress test-2021 09 30-14_35_22](https://user-images.githubusercontent.com/1314156/135506748-0b7bdce5-b006-47f9-9289-03ed26e4950c.png)
|
||||||
|
|
||||||
9. Select `Subscription product` and press `Ok`. You should have been redirected to `post-new.php?post_type=product&subscription_pointers=true`
|
18. Select `Subscription product` and press `Ok`. You should have been redirected to `post-new.php?post_type=product&subscription_pointers=true`.
|
||||||
|
|
||||||
## 2.7.1
|
## 2.7.1
|
||||||
|
|
||||||
|
|
|
@ -80,11 +80,8 @@ class CartModal extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderProducts() {
|
renderProducts() {
|
||||||
const { productIds } = this.props;
|
const { productIds, productTypes } = this.props;
|
||||||
const { productTypes = {}, themes = [] } = getSetting(
|
const { themes = [] } = getSetting( 'onboarding', {} );
|
||||||
'onboarding',
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
const listItems = [];
|
const listItems = [];
|
||||||
|
|
||||||
productIds.forEach( ( productId ) => {
|
productIds.forEach( ( productId ) => {
|
||||||
|
@ -169,15 +166,19 @@ class CartModal extends Component {
|
||||||
export default compose(
|
export default compose(
|
||||||
withSelect( ( select ) => {
|
withSelect( ( select ) => {
|
||||||
const { getInstalledPlugins } = select( PLUGINS_STORE_NAME );
|
const { getInstalledPlugins } = select( PLUGINS_STORE_NAME );
|
||||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
const { getProductTypes, getProfileItems } = select(
|
||||||
|
ONBOARDING_STORE_NAME
|
||||||
|
);
|
||||||
const profileItems = getProfileItems();
|
const profileItems = getProfileItems();
|
||||||
const installedPlugins = getInstalledPlugins();
|
const installedPlugins = getInstalledPlugins();
|
||||||
|
const productTypes = getProductTypes();
|
||||||
const productIds = getProductIdsForCart(
|
const productIds = getProductIdsForCart(
|
||||||
|
productTypes,
|
||||||
profileItems,
|
profileItems,
|
||||||
false,
|
false,
|
||||||
installedPlugins
|
installedPlugins
|
||||||
);
|
);
|
||||||
|
|
||||||
return { profileItems, productIds };
|
return { profileItems, productIds, productTypes };
|
||||||
} )
|
} )
|
||||||
)( CartModal );
|
)( CartModal );
|
||||||
|
|
|
@ -36,12 +36,14 @@ export function getCurrencyRegion( countryState ) {
|
||||||
/**
|
/**
|
||||||
* Gets the product IDs for items based on the product types and theme selected in the onboarding profiler.
|
* Gets the product IDs for items based on the product types and theme selected in the onboarding profiler.
|
||||||
*
|
*
|
||||||
|
* @param {Object} productTypes Product Types.
|
||||||
* @param {Object} profileItems Onboarding profile.
|
* @param {Object} profileItems Onboarding profile.
|
||||||
* @param {boolean} includeInstalledItems Include installed items in returned product IDs.
|
* @param {boolean} includeInstalledItems Include installed items in returned product IDs.
|
||||||
* @param {Array} installedPlugins Installed plugins.
|
* @param {Array} installedPlugins Installed plugins.
|
||||||
* @return {Array} Product Ids.
|
* @return {Array} Product Ids.
|
||||||
*/
|
*/
|
||||||
export function getProductIdsForCart(
|
export function getProductIdsForCart(
|
||||||
|
productTypes,
|
||||||
profileItems,
|
profileItems,
|
||||||
includeInstalledItems = false,
|
includeInstalledItems = false,
|
||||||
installedPlugins
|
installedPlugins
|
||||||
|
@ -49,7 +51,8 @@ export function getProductIdsForCart(
|
||||||
const productList = getProductList(
|
const productList = getProductList(
|
||||||
profileItems,
|
profileItems,
|
||||||
includeInstalledItems,
|
includeInstalledItems,
|
||||||
installedPlugins
|
installedPlugins,
|
||||||
|
productTypes
|
||||||
);
|
);
|
||||||
const productIds = productList.map(
|
const productIds = productList.map(
|
||||||
( product ) => product.id || product.product
|
( product ) => product.id || product.product
|
||||||
|
@ -60,11 +63,13 @@ export function getProductIdsForCart(
|
||||||
/**
|
/**
|
||||||
* Gets the labeled/categorized product names and types for items based on the product types and theme selected in the onboarding profiler.
|
* Gets the labeled/categorized product names and types for items based on the product types and theme selected in the onboarding profiler.
|
||||||
*
|
*
|
||||||
|
* @param {Object} productTypes Product Types.
|
||||||
* @param {Object} profileItems Onboarding profile.
|
* @param {Object} profileItems Onboarding profile.
|
||||||
* @param {Array} installedPlugins Installed plugins.
|
* @param {Array} installedPlugins Installed plugins.
|
||||||
* @return {Array} Objects with labeled/categorized product names and types.
|
* @return {Array} Objects with labeled/categorized product names and types.
|
||||||
*/
|
*/
|
||||||
export function getCategorizedOnboardingProducts(
|
export function getCategorizedOnboardingProducts(
|
||||||
|
productTypes,
|
||||||
profileItems,
|
profileItems,
|
||||||
installedPlugins
|
installedPlugins
|
||||||
) {
|
) {
|
||||||
|
@ -72,12 +77,14 @@ export function getCategorizedOnboardingProducts(
|
||||||
productList.products = getProductList(
|
productList.products = getProductList(
|
||||||
profileItems,
|
profileItems,
|
||||||
true,
|
true,
|
||||||
installedPlugins
|
installedPlugins,
|
||||||
|
productTypes
|
||||||
);
|
);
|
||||||
productList.remainingProducts = getProductList(
|
productList.remainingProducts = getProductList(
|
||||||
profileItems,
|
profileItems,
|
||||||
false,
|
false,
|
||||||
installedPlugins
|
installedPlugins,
|
||||||
|
productTypes
|
||||||
);
|
);
|
||||||
|
|
||||||
const uniqueItemsList = [
|
const uniqueItemsList = [
|
||||||
|
@ -106,37 +113,37 @@ export function getCategorizedOnboardingProducts(
|
||||||
* @param {Object} profileItems Onboarding profile.
|
* @param {Object} profileItems Onboarding profile.
|
||||||
* @param {boolean} includeInstalledItems Include installed items in returned product list.
|
* @param {boolean} includeInstalledItems Include installed items in returned product list.
|
||||||
* @param {Array} installedPlugins Installed plugins.
|
* @param {Array} installedPlugins Installed plugins.
|
||||||
|
* @param {Object} productTypes Product Types.
|
||||||
* @return {Array} Products.
|
* @return {Array} Products.
|
||||||
*/
|
*/
|
||||||
export function getProductList(
|
export function getProductList(
|
||||||
profileItems,
|
profileItems,
|
||||||
includeInstalledItems = false,
|
includeInstalledItems = false,
|
||||||
installedPlugins
|
installedPlugins,
|
||||||
|
productTypes
|
||||||
) {
|
) {
|
||||||
const onboarding = getSetting( 'onboarding', {} );
|
|
||||||
const productList = [];
|
const productList = [];
|
||||||
|
|
||||||
// The population of onboarding.productTypes only happens if the task list should be shown
|
if ( ! productTypes ) {
|
||||||
// so bail early if it isn't present.
|
|
||||||
if ( ! onboarding.productTypes ) {
|
|
||||||
return productList;
|
return productList;
|
||||||
}
|
}
|
||||||
|
|
||||||
const productTypes = profileItems.product_types || [];
|
const profileItemsProductTypes = profileItems.product_types || [];
|
||||||
|
|
||||||
productTypes.forEach( ( productType ) => {
|
profileItemsProductTypes.forEach( ( productType ) => {
|
||||||
if (
|
if (
|
||||||
onboarding.productTypes[ productType ] &&
|
productTypes[ productType ] &&
|
||||||
onboarding.productTypes[ productType ].product &&
|
productTypes[ productType ].product &&
|
||||||
( includeInstalledItems ||
|
( includeInstalledItems ||
|
||||||
! installedPlugins.includes(
|
! installedPlugins.includes(
|
||||||
onboarding.productTypes[ productType ].slug
|
productTypes[ productType ].slug
|
||||||
) )
|
) )
|
||||||
) {
|
) {
|
||||||
productList.push( onboarding.productTypes[ productType ] );
|
productList.push( productTypes[ productType ] );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
const onboarding = getSetting( 'onboarding', {} );
|
||||||
const theme = onboarding.themes.find(
|
const theme = onboarding.themes.find(
|
||||||
( themeData ) => themeData.slug === profileItems.theme
|
( themeData ) => themeData.slug === profileItems.theme
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,7 +8,11 @@ import { Link } from '@woocommerce/components';
|
||||||
import { __, _n, sprintf } from '@wordpress/i18n';
|
import { __, _n, sprintf } from '@wordpress/i18n';
|
||||||
import { Icon, chevronDown, chevronUp } from '@wordpress/icons';
|
import { Icon, chevronDown, chevronUp } from '@wordpress/icons';
|
||||||
import interpolateComponents from 'interpolate-components';
|
import interpolateComponents from 'interpolate-components';
|
||||||
import { pluginNames, ONBOARDING_STORE_NAME } from '@woocommerce/data';
|
import {
|
||||||
|
pluginNames,
|
||||||
|
ONBOARDING_STORE_NAME,
|
||||||
|
SETTINGS_STORE_NAME,
|
||||||
|
} from '@woocommerce/data';
|
||||||
import { recordEvent } from '@woocommerce/tracks';
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useSelect } from '@wordpress/data';
|
||||||
|
|
||||||
|
@ -19,6 +23,7 @@ import { AppIllustration } from '../app-illustration';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
import sanitizeHTML from '~/lib/sanitize-html';
|
import sanitizeHTML from '~/lib/sanitize-html';
|
||||||
import { setAllPropsToValue } from '~/lib/collections';
|
import { setAllPropsToValue } from '~/lib/collections';
|
||||||
|
import { getCountryCode } from '../../../../../../dashboard/utils';
|
||||||
|
|
||||||
const ALLOWED_PLUGIN_LISTS = [ 'basics' ];
|
const ALLOWED_PLUGIN_LISTS = [ 'basics' ];
|
||||||
|
|
||||||
|
@ -178,28 +183,35 @@ export const SelectiveExtensionsBundle = ( {
|
||||||
const [ showExtensions, setShowExtensions ] = useState( false );
|
const [ showExtensions, setShowExtensions ] = useState( false );
|
||||||
const [ values, setValues ] = useState( baseValues );
|
const [ values, setValues ] = useState( baseValues );
|
||||||
|
|
||||||
const { freeExtensions, isResolving, profileItems } = useSelect(
|
const {
|
||||||
( select ) => {
|
countryCode,
|
||||||
|
freeExtensions,
|
||||||
|
isResolving,
|
||||||
|
profileItems,
|
||||||
|
} = useSelect( ( select ) => {
|
||||||
const {
|
const {
|
||||||
getFreeExtensions,
|
getFreeExtensions,
|
||||||
getProfileItems,
|
getProfileItems,
|
||||||
hasFinishedResolution,
|
hasFinishedResolution,
|
||||||
} = select( ONBOARDING_STORE_NAME );
|
} = select( ONBOARDING_STORE_NAME );
|
||||||
|
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||||
|
const { general: settings = {} } = getSettings( 'general' );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
countryCode: getCountryCode( settings.woocommerce_default_country ),
|
||||||
freeExtensions: getFreeExtensions(),
|
freeExtensions: getFreeExtensions(),
|
||||||
isResolving: ! hasFinishedResolution( 'getFreeExtensions' ),
|
isResolving: ! hasFinishedResolution( 'getFreeExtensions' ),
|
||||||
profileItems: getProfileItems(),
|
profileItems: getProfileItems(),
|
||||||
};
|
};
|
||||||
}
|
} );
|
||||||
);
|
|
||||||
|
|
||||||
const installableExtensions = useMemo( () => {
|
const installableExtensions = useMemo( () => {
|
||||||
const { product_types: productTypes } = profileItems;
|
const { product_types: productTypes } = profileItems;
|
||||||
return freeExtensions.filter( ( list ) => {
|
return freeExtensions.filter( ( list ) => {
|
||||||
if (
|
if (
|
||||||
window.wcAdminFeatures &&
|
window.wcAdminFeatures &&
|
||||||
window.wcAdminFeatures.subscriptions
|
window.wcAdminFeatures.subscriptions &&
|
||||||
|
countryCode === 'US'
|
||||||
) {
|
) {
|
||||||
if ( productTypes.includes( 'subscriptions' ) ) {
|
if ( productTypes.includes( 'subscriptions' ) ) {
|
||||||
list.plugins = list.plugins.filter(
|
list.plugins = list.plugins.filter(
|
||||||
|
|
|
@ -11,35 +11,34 @@ import {
|
||||||
CardFooter,
|
CardFooter,
|
||||||
CheckboxControl,
|
CheckboxControl,
|
||||||
FormToggle,
|
FormToggle,
|
||||||
|
Spinner,
|
||||||
} from '@wordpress/components';
|
} from '@wordpress/components';
|
||||||
import { includes, filter, get } from 'lodash';
|
import { includes, filter } from 'lodash';
|
||||||
import { getSetting } from '@woocommerce/wc-admin-settings';
|
|
||||||
import { recordEvent } from '@woocommerce/tracks';
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
import { withDispatch, withSelect } from '@wordpress/data';
|
import { withDispatch, withSelect } from '@wordpress/data';
|
||||||
import { ONBOARDING_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data';
|
import {
|
||||||
|
ONBOARDING_STORE_NAME,
|
||||||
|
PLUGINS_STORE_NAME,
|
||||||
|
SETTINGS_STORE_NAME,
|
||||||
|
} from '@woocommerce/data';
|
||||||
import { Text } from '@woocommerce/experimental';
|
import { Text } from '@woocommerce/experimental';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { createNoticesFromResponse } from '~/lib/notices';
|
import { createNoticesFromResponse } from '~/lib/notices';
|
||||||
|
import { getCountryCode } from '../../../dashboard/utils';
|
||||||
import ProductTypeLabel from './label';
|
import ProductTypeLabel from './label';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
export class ProductTypes extends Component {
|
export class ProductTypes extends Component {
|
||||||
constructor( props ) {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
const profileItems = get( props, 'profileItems', {} );
|
|
||||||
|
|
||||||
const { productTypes = {} } = getSetting( 'onboarding', {} );
|
|
||||||
const defaultProductTypes = Object.keys( productTypes ).filter(
|
|
||||||
( key ) => !! productTypes[ key ].default
|
|
||||||
);
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
error: null,
|
error: null,
|
||||||
isMonthlyPricing: true,
|
isMonthlyPricing: true,
|
||||||
selected: profileItems.product_types || defaultProductTypes,
|
selected: [],
|
||||||
isWCPayInstalled: null,
|
isWCPayInstalled: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,9 +47,11 @@ export class ProductTypes extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { installedPlugins } = this.props;
|
const { installedPlugins, invalidateResolution } = this.props;
|
||||||
const { isWCPayInstalled } = this.state;
|
const { isWCPayInstalled } = this.state;
|
||||||
|
|
||||||
|
invalidateResolution( 'getProductTypes', [] );
|
||||||
|
|
||||||
if ( isWCPayInstalled === null && installedPlugins ) {
|
if ( isWCPayInstalled === null && installedPlugins ) {
|
||||||
this.setState( {
|
this.setState( {
|
||||||
isWCPayInstalled: installedPlugins.includes(
|
isWCPayInstalled: installedPlugins.includes(
|
||||||
|
@ -60,6 +61,19 @@ export class ProductTypes extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate( prevProps ) {
|
||||||
|
const { profileItems, productTypes } = this.props;
|
||||||
|
|
||||||
|
if ( prevProps.productTypes !== productTypes ) {
|
||||||
|
const defaultProductTypes = Object.keys( productTypes ).filter(
|
||||||
|
( key ) => !! productTypes[ key ].default
|
||||||
|
);
|
||||||
|
this.setState( {
|
||||||
|
selected: profileItems.product_types || defaultProductTypes,
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validateField() {
|
validateField() {
|
||||||
const error = this.state.selected.length
|
const error = this.state.selected.length
|
||||||
? null
|
? null
|
||||||
|
@ -80,6 +94,7 @@ export class ProductTypes extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
countryCode,
|
||||||
createNotice,
|
createNotice,
|
||||||
goToNextStep,
|
goToNextStep,
|
||||||
installAndActivatePlugins,
|
installAndActivatePlugins,
|
||||||
|
@ -95,6 +110,7 @@ export class ProductTypes extends Component {
|
||||||
if (
|
if (
|
||||||
window.wcAdminFeatures &&
|
window.wcAdminFeatures &&
|
||||||
window.wcAdminFeatures.subscriptions &&
|
window.wcAdminFeatures.subscriptions &&
|
||||||
|
countryCode === 'US' &&
|
||||||
! installedPlugins.includes( 'woocommerce-payments' ) &&
|
! installedPlugins.includes( 'woocommerce-payments' ) &&
|
||||||
selected.includes( 'subscriptions' )
|
selected.includes( 'subscriptions' )
|
||||||
) {
|
) {
|
||||||
|
@ -145,14 +161,27 @@ export class ProductTypes extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { productTypes = {} } = getSetting( 'onboarding', {} );
|
const { productTypes = [] } = this.props;
|
||||||
const {
|
const {
|
||||||
error,
|
error,
|
||||||
isMonthlyPricing,
|
isMonthlyPricing,
|
||||||
isWCPayInstalled,
|
isWCPayInstalled,
|
||||||
selected,
|
selected,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { isInstallingActivating, isProfileItemsRequesting } = this.props;
|
const {
|
||||||
|
countryCode,
|
||||||
|
isInstallingActivating,
|
||||||
|
isProductTypesRequesting,
|
||||||
|
isProfileItemsRequesting,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if ( isProductTypesRequesting ) {
|
||||||
|
return (
|
||||||
|
<div className="woocommerce-profile-wizard__product-types__spinner">
|
||||||
|
<Spinner />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="woocommerce-profile-wizard__product-types">
|
<div className="woocommerce-profile-wizard__product-types">
|
||||||
|
@ -256,6 +285,7 @@ export class ProductTypes extends Component {
|
||||||
</Text>
|
</Text>
|
||||||
{ window.wcAdminFeatures &&
|
{ window.wcAdminFeatures &&
|
||||||
window.wcAdminFeatures.subscriptions &&
|
window.wcAdminFeatures.subscriptions &&
|
||||||
|
countryCode === 'US' &&
|
||||||
! isWCPayInstalled &&
|
! isWCPayInstalled &&
|
||||||
selected.includes( 'subscriptions' ) && (
|
selected.includes( 'subscriptions' ) && (
|
||||||
<Text
|
<Text
|
||||||
|
@ -280,12 +310,16 @@ export default compose(
|
||||||
withSelect( ( select ) => {
|
withSelect( ( select ) => {
|
||||||
const {
|
const {
|
||||||
getProfileItems,
|
getProfileItems,
|
||||||
|
getProductTypes,
|
||||||
getOnboardingError,
|
getOnboardingError,
|
||||||
|
hasFinishedResolution,
|
||||||
isOnboardingRequesting,
|
isOnboardingRequesting,
|
||||||
} = select( ONBOARDING_STORE_NAME );
|
} = select( ONBOARDING_STORE_NAME );
|
||||||
|
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||||
const { getInstalledPlugins, isPluginsRequesting } = select(
|
const { getInstalledPlugins, isPluginsRequesting } = select(
|
||||||
PLUGINS_STORE_NAME
|
PLUGINS_STORE_NAME
|
||||||
);
|
);
|
||||||
|
const { general: settings = {} } = getSettings( 'general' );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isError: Boolean( getOnboardingError( 'updateProfileItems' ) ),
|
isError: Boolean( getOnboardingError( 'updateProfileItems' ) ),
|
||||||
|
@ -297,16 +331,23 @@ export default compose(
|
||||||
isInstallingActivating:
|
isInstallingActivating:
|
||||||
isPluginsRequesting( 'installPlugins' ) ||
|
isPluginsRequesting( 'installPlugins' ) ||
|
||||||
isPluginsRequesting( 'activatePlugins' ),
|
isPluginsRequesting( 'activatePlugins' ),
|
||||||
|
countryCode: getCountryCode( settings.woocommerce_default_country ),
|
||||||
|
productTypes: getProductTypes(),
|
||||||
|
isProductTypesRequesting: ! hasFinishedResolution(
|
||||||
|
'getProductTypes'
|
||||||
|
),
|
||||||
};
|
};
|
||||||
} ),
|
} ),
|
||||||
withDispatch( ( dispatch ) => {
|
withDispatch( ( dispatch ) => {
|
||||||
const { updateProfileItems } = dispatch( ONBOARDING_STORE_NAME );
|
const { updateProfileItems } = dispatch( ONBOARDING_STORE_NAME );
|
||||||
const { createNotice } = dispatch( 'core/notices' );
|
const { createNotice } = dispatch( 'core/notices' );
|
||||||
const { installAndActivatePlugins } = dispatch( PLUGINS_STORE_NAME );
|
const { installAndActivatePlugins } = dispatch( PLUGINS_STORE_NAME );
|
||||||
|
const { invalidateResolution } = dispatch( ONBOARDING_STORE_NAME );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createNotice,
|
createNotice,
|
||||||
installAndActivatePlugins,
|
installAndActivatePlugins,
|
||||||
|
invalidateResolution,
|
||||||
updateProfileItems,
|
updateProfileItems,
|
||||||
};
|
};
|
||||||
} )
|
} )
|
||||||
|
|
|
@ -60,6 +60,9 @@
|
||||||
margin-left: $gap;
|
margin-left: $gap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&__spinner {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,17 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
import { setSetting } from '@woocommerce/wc-admin-settings';
|
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { createElement } from '@wordpress/element';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { ProductTypes } from '../';
|
import { ProductTypes } from '../';
|
||||||
|
|
||||||
describe( 'ProductTypes', () => {
|
const testProps = {
|
||||||
beforeEach( () => {
|
countryCode: 'US',
|
||||||
setSetting( 'onboarding', {
|
invalidateResolution: jest.fn(),
|
||||||
|
isProductTypesRequesting: false,
|
||||||
productTypes: {
|
productTypes: {
|
||||||
paidProduct: {
|
paidProduct: {
|
||||||
description: 'Paid product type',
|
description: 'Paid product type',
|
||||||
|
@ -27,21 +26,20 @@ describe( 'ProductTypes', () => {
|
||||||
label: 'Free product',
|
label: 'Free product',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} );
|
};
|
||||||
} );
|
|
||||||
|
|
||||||
|
describe( 'ProductTypes', () => {
|
||||||
afterEach( () => {
|
afterEach( () => {
|
||||||
setSetting( 'onboarding', {} );
|
|
||||||
window.wcAdminFeatures.subscriptions = false;
|
window.wcAdminFeatures.subscriptions = false;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should render product types', () => {
|
test( 'should render product types', () => {
|
||||||
const { container } = render( <ProductTypes /> );
|
const { container } = render( <ProductTypes { ...testProps } /> );
|
||||||
expect( container ).toMatchSnapshot();
|
expect( container ).toMatchSnapshot();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should show annual prices on toggle', () => {
|
test( 'should show annual prices on toggle', () => {
|
||||||
const { container } = render( <ProductTypes /> );
|
const { container } = render( <ProductTypes { ...testProps } /> );
|
||||||
|
|
||||||
const toggle = screen.getByLabelText( 'Display monthly prices', {
|
const toggle = screen.getByLabelText( 'Display monthly prices', {
|
||||||
selector: 'input',
|
selector: 'input',
|
||||||
|
@ -62,6 +60,7 @@ describe( 'ProductTypes', () => {
|
||||||
createNotice={ mockCreateNotice }
|
createNotice={ mockCreateNotice }
|
||||||
goToNextStep={ mockGoToNextStep }
|
goToNextStep={ mockGoToNextStep }
|
||||||
updateProfileItems={ mockUpdateProfileItems }
|
updateProfileItems={ mockUpdateProfileItems }
|
||||||
|
{ ...testProps }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -88,16 +87,16 @@ describe( 'ProductTypes', () => {
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
test( 'should show a warning message at the bottom of the step', () => {
|
test( 'should show a warning message at the bottom of the step', () => {
|
||||||
setSetting( 'onboarding', {
|
const productTypes = {
|
||||||
productTypes: {
|
|
||||||
subscriptions: {
|
subscriptions: {
|
||||||
label: 'Subscriptions',
|
label: 'Subscriptions',
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
} );
|
|
||||||
window.wcAdminFeatures.subscriptions = true;
|
window.wcAdminFeatures.subscriptions = true;
|
||||||
|
|
||||||
render( <ProductTypes /> );
|
render(
|
||||||
|
<ProductTypes { ...testProps } productTypes={ productTypes } />
|
||||||
|
);
|
||||||
|
|
||||||
const subscription = screen.getByText( 'Subscriptions', {
|
const subscription = screen.getByText( 'Subscriptions', {
|
||||||
selector: 'label',
|
selector: 'label',
|
||||||
|
@ -110,4 +109,32 @@ describe( 'ProductTypes', () => {
|
||||||
)
|
)
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
} );
|
} );
|
||||||
|
test( 'should show the warning message only for US stores', () => {
|
||||||
|
const productTypes = {
|
||||||
|
subscriptions: {
|
||||||
|
label: 'Subscriptions',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const countryCode = 'FR';
|
||||||
|
window.wcAdminFeatures.subscriptions = true;
|
||||||
|
|
||||||
|
render(
|
||||||
|
<ProductTypes
|
||||||
|
{ ...testProps }
|
||||||
|
productTypes={ productTypes }
|
||||||
|
countryCode={ countryCode }
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const subscription = screen.getByText( 'Subscriptions', {
|
||||||
|
selector: 'label',
|
||||||
|
} );
|
||||||
|
userEvent.click( subscription );
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.queryByText(
|
||||||
|
'The following extensions will be added to your site for free: WooCommerce Payments. An account is required to use this feature.'
|
||||||
|
)
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -230,7 +230,13 @@ class StoreDetails extends Component {
|
||||||
isStoreDetailsPopoverVisible,
|
isStoreDetailsPopoverVisible,
|
||||||
isSkipSetupPopoverVisible,
|
isSkipSetupPopoverVisible,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { skipProfiler, isLoading, isBusy, initialValues } = this.props;
|
const {
|
||||||
|
skipProfiler,
|
||||||
|
isLoading,
|
||||||
|
isBusy,
|
||||||
|
initialValues,
|
||||||
|
invalidateResolutionForStoreSelector,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
/* eslint-disable @wordpress/i18n-no-collapsible-whitespace */
|
/* eslint-disable @wordpress/i18n-no-collapsible-whitespace */
|
||||||
const skipSetupText = __(
|
const skipSetupText = __(
|
||||||
|
@ -390,6 +396,9 @@ class StoreDetails extends Component {
|
||||||
isLink
|
isLink
|
||||||
className="woocommerce-profile-wizard__footer-link"
|
className="woocommerce-profile-wizard__footer-link"
|
||||||
onClick={ () => {
|
onClick={ () => {
|
||||||
|
invalidateResolutionForStoreSelector(
|
||||||
|
'getTaskLists'
|
||||||
|
);
|
||||||
this.setState( {
|
this.setState( {
|
||||||
showUsageModal: true,
|
showUsageModal: true,
|
||||||
skipping: true,
|
skipping: true,
|
||||||
|
@ -498,13 +507,17 @@ export default compose(
|
||||||
} ),
|
} ),
|
||||||
withDispatch( ( dispatch ) => {
|
withDispatch( ( dispatch ) => {
|
||||||
const { createNotice } = dispatch( 'core/notices' );
|
const { createNotice } = dispatch( 'core/notices' );
|
||||||
const { updateProfileItems } = dispatch( ONBOARDING_STORE_NAME );
|
const {
|
||||||
|
invalidateResolutionForStoreSelector,
|
||||||
|
updateProfileItems,
|
||||||
|
} = dispatch( ONBOARDING_STORE_NAME );
|
||||||
const { updateAndPersistSettingsForGroup } = dispatch(
|
const { updateAndPersistSettingsForGroup } = dispatch(
|
||||||
SETTINGS_STORE_NAME
|
SETTINGS_STORE_NAME
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createNotice,
|
createNotice,
|
||||||
|
invalidateResolutionForStoreSelector,
|
||||||
updateProfileItems,
|
updateProfileItems,
|
||||||
updateAndPersistSettingsForGroup,
|
updateAndPersistSettingsForGroup,
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,11 +5,12 @@ import { __ } from '@wordpress/i18n';
|
||||||
import { Button, Modal, RadioControl } from '@wordpress/components';
|
import { Button, Modal, RadioControl } from '@wordpress/components';
|
||||||
import { useState } from '@wordpress/element';
|
import { useState } from '@wordpress/element';
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
import { addFilter, applyFilters } from '@wordpress/hooks';
|
import { applyFilters } from '@wordpress/hooks';
|
||||||
import {
|
import {
|
||||||
ITEMS_STORE_NAME,
|
ITEMS_STORE_NAME,
|
||||||
ONBOARDING_STORE_NAME,
|
ONBOARDING_STORE_NAME,
|
||||||
PLUGINS_STORE_NAME,
|
PLUGINS_STORE_NAME,
|
||||||
|
SETTINGS_STORE_NAME,
|
||||||
} from '@woocommerce/data';
|
} from '@woocommerce/data';
|
||||||
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
||||||
import { recordEvent } from '@woocommerce/tracks';
|
import { recordEvent } from '@woocommerce/tracks';
|
||||||
|
@ -19,11 +20,12 @@ import { recordEvent } from '@woocommerce/tracks';
|
||||||
*/
|
*/
|
||||||
import './product-template-modal.scss';
|
import './product-template-modal.scss';
|
||||||
import { createNoticesFromResponse } from '../../../lib/notices';
|
import { createNoticesFromResponse } from '../../../lib/notices';
|
||||||
|
import { getCountryCode } from '../../../dashboard/utils';
|
||||||
|
|
||||||
export const ONBOARDING_PRODUCT_TEMPLATES_FILTER =
|
export const ONBOARDING_PRODUCT_TEMPLATES_FILTER =
|
||||||
'woocommerce_admin_onboarding_product_templates';
|
'woocommerce_admin_onboarding_product_templates';
|
||||||
|
|
||||||
const PRODUCT_TEMPLATES = [
|
const getProductTemplates = () => [
|
||||||
{
|
{
|
||||||
key: 'physical',
|
key: 'physical',
|
||||||
title: __( 'Physical product', 'woocommerce-admin' ),
|
title: __( 'Physical product', 'woocommerce-admin' ),
|
||||||
|
@ -62,10 +64,13 @@ export default function ProductTemplateModal( { onClose } ) {
|
||||||
const [ selectedTemplate, setSelectedTemplate ] = useState( null );
|
const [ selectedTemplate, setSelectedTemplate ] = useState( null );
|
||||||
const [ isRedirecting, setIsRedirecting ] = useState( false );
|
const [ isRedirecting, setIsRedirecting ] = useState( false );
|
||||||
const { createProductFromTemplate } = useDispatch( ITEMS_STORE_NAME );
|
const { createProductFromTemplate } = useDispatch( ITEMS_STORE_NAME );
|
||||||
const { profileItems } = useSelect( ( select ) => {
|
const { countryCode, profileItems } = useSelect( ( select ) => {
|
||||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
||||||
|
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||||
|
const { general: settings = {} } = getSettings( 'general' );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
countryCode: getCountryCode( settings.woocommerce_default_country ),
|
||||||
profileItems: getProfileItems(),
|
profileItems: getProfileItems(),
|
||||||
};
|
};
|
||||||
} );
|
} );
|
||||||
|
@ -116,25 +121,21 @@ export default function ProductTemplateModal( { onClose } ) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
const removeSubscriptions =
|
||||||
( window.wcAdminFeatures && ! window.wcAdminFeatures.subscriptions ) ||
|
( window.wcAdminFeatures && ! window.wcAdminFeatures.subscriptions ) ||
|
||||||
|
countryCode !== 'US' ||
|
||||||
! profileItems.product_types.includes( 'subscriptions' ) ||
|
! profileItems.product_types.includes( 'subscriptions' ) ||
|
||||||
! installedPlugins.includes( 'woocommerce-payments' )
|
! installedPlugins.includes( 'woocommerce-payments' );
|
||||||
) {
|
|
||||||
addFilter(
|
const productTemplates = removeSubscriptions
|
||||||
ONBOARDING_PRODUCT_TEMPLATES_FILTER,
|
? getProductTemplates().filter(
|
||||||
'woocommerce-admin',
|
|
||||||
( productTemplates ) => {
|
|
||||||
return productTemplates.filter(
|
|
||||||
( template ) => template.key !== 'subscription'
|
( template ) => template.key !== 'subscription'
|
||||||
);
|
)
|
||||||
}
|
: getProductTemplates();
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const templates = applyFilters(
|
const templates = applyFilters(
|
||||||
ONBOARDING_PRODUCT_TEMPLATES_FILTER,
|
ONBOARDING_PRODUCT_TEMPLATES_FILTER,
|
||||||
PRODUCT_TEMPLATES
|
productTemplates
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -12,7 +12,11 @@ import {
|
||||||
archive,
|
archive,
|
||||||
download,
|
download,
|
||||||
} from '@wordpress/icons';
|
} from '@wordpress/icons';
|
||||||
import { ONBOARDING_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data';
|
import {
|
||||||
|
ONBOARDING_STORE_NAME,
|
||||||
|
PLUGINS_STORE_NAME,
|
||||||
|
SETTINGS_STORE_NAME,
|
||||||
|
} from '@woocommerce/data';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useSelect } from '@wordpress/data';
|
||||||
import { List, Pill } from '@woocommerce/components';
|
import { List, Pill } from '@woocommerce/components';
|
||||||
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
||||||
|
@ -24,8 +28,9 @@ import { WooOnboardingTask } from '@woocommerce/onboarding';
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import ProductTemplateModal from './product-template-modal';
|
import ProductTemplateModal from './product-template-modal';
|
||||||
|
import { getCountryCode } from '../../../dashboard/utils';
|
||||||
|
|
||||||
const subTasks = [
|
const getSubTasks = () => [
|
||||||
{
|
{
|
||||||
key: 'addProductTemplate',
|
key: 'addProductTemplate',
|
||||||
title: (
|
title: (
|
||||||
|
@ -94,10 +99,13 @@ const subTasks = [
|
||||||
|
|
||||||
const Products = () => {
|
const Products = () => {
|
||||||
const [ selectTemplate, setSelectTemplate ] = useState( null );
|
const [ selectTemplate, setSelectTemplate ] = useState( null );
|
||||||
const { profileItems } = useSelect( ( select ) => {
|
const { countryCode, profileItems } = useSelect( ( select ) => {
|
||||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
||||||
|
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||||
|
const { general: settings = {} } = getSettings( 'general' );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
countryCode: getCountryCode( settings.woocommerce_default_country ),
|
||||||
profileItems: getProfileItems(),
|
profileItems: getProfileItems(),
|
||||||
};
|
};
|
||||||
} );
|
} );
|
||||||
|
@ -109,9 +117,12 @@ const Products = () => {
|
||||||
};
|
};
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
const subTasks = getSubTasks();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
window.wcAdminFeatures &&
|
window.wcAdminFeatures &&
|
||||||
window.wcAdminFeatures.subscriptions &&
|
window.wcAdminFeatures.subscriptions &&
|
||||||
|
countryCode === 'US' &&
|
||||||
profileItems.product_types.includes( 'subscriptions' ) &&
|
profileItems.product_types.includes( 'subscriptions' ) &&
|
||||||
installedPlugins.includes( 'woocommerce-payments' )
|
installedPlugins.includes( 'woocommerce-payments' )
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -18,15 +18,20 @@ import { getCategorizedOnboardingProducts } from '../../dashboard/utils';
|
||||||
const PurchaseTaskItem = () => {
|
const PurchaseTaskItem = () => {
|
||||||
const [ cartModalOpen, setCartModalOpen ] = useState( false );
|
const [ cartModalOpen, setCartModalOpen ] = useState( false );
|
||||||
|
|
||||||
const { installedPlugins, profileItems } = useSelect( ( select ) => {
|
const { installedPlugins, productTypes, profileItems } = useSelect(
|
||||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
( select ) => {
|
||||||
|
const { getProductTypes, getProfileItems } = select(
|
||||||
|
ONBOARDING_STORE_NAME
|
||||||
|
);
|
||||||
const { getInstalledPlugins } = select( PLUGINS_STORE_NAME );
|
const { getInstalledPlugins } = select( PLUGINS_STORE_NAME );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
installedPlugins: getInstalledPlugins(),
|
installedPlugins: getInstalledPlugins(),
|
||||||
|
productTypes: getProductTypes(),
|
||||||
profileItems: getProfileItems(),
|
profileItems: getProfileItems(),
|
||||||
};
|
};
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const toggleCartModal = useCallback( () => {
|
const toggleCartModal = useCallback( () => {
|
||||||
if ( ! cartModalOpen ) {
|
if ( ! cartModalOpen ) {
|
||||||
|
@ -37,6 +42,7 @@ const PurchaseTaskItem = () => {
|
||||||
}, [ cartModalOpen ] );
|
}, [ cartModalOpen ] );
|
||||||
|
|
||||||
const groupedProducts = getCategorizedOnboardingProducts(
|
const groupedProducts = getCategorizedOnboardingProducts(
|
||||||
|
productTypes,
|
||||||
profileItems,
|
profileItems,
|
||||||
installedPlugins
|
installedPlugins
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,6 +5,8 @@ const TYPES = {
|
||||||
SET_EMAIL_PREFILL: 'SET_EMAIL_PREFILL',
|
SET_EMAIL_PREFILL: 'SET_EMAIL_PREFILL',
|
||||||
SET_TASKS_STATUS: 'SET_TASKS_STATUS',
|
SET_TASKS_STATUS: 'SET_TASKS_STATUS',
|
||||||
GET_PAYMENT_METHODS_SUCCESS: 'GET_PAYMENT_METHODS_SUCCESS',
|
GET_PAYMENT_METHODS_SUCCESS: 'GET_PAYMENT_METHODS_SUCCESS',
|
||||||
|
GET_PRODUCT_TYPES_SUCCESS: 'GET_PRODUCT_TYPES_SUCCESS',
|
||||||
|
GET_PRODUCT_TYPES_ERROR: 'GET_PRODUCT_TYPES_ERROR',
|
||||||
GET_FREE_EXTENSIONS_ERROR: 'GET_FREE_EXTENSIONS_ERROR',
|
GET_FREE_EXTENSIONS_ERROR: 'GET_FREE_EXTENSIONS_ERROR',
|
||||||
GET_FREE_EXTENSIONS_SUCCESS: 'GET_FREE_EXTENSIONS_SUCCESS',
|
GET_FREE_EXTENSIONS_SUCCESS: 'GET_FREE_EXTENSIONS_SUCCESS',
|
||||||
GET_TASK_LISTS_ERROR: 'GET_TASK_LISTS_ERROR',
|
GET_TASK_LISTS_ERROR: 'GET_TASK_LISTS_ERROR',
|
||||||
|
|
|
@ -222,6 +222,20 @@ export function actionTaskSuccess( task ) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getProductTypesSuccess( productTypes ) {
|
||||||
|
return {
|
||||||
|
type: TYPES.GET_PRODUCT_TYPES_SUCCESS,
|
||||||
|
productTypes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getProductTypesError( error ) {
|
||||||
|
return {
|
||||||
|
type: TYPES.GET_PRODUCT_TYPES_ERROR,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function* updateProfileItems( items ) {
|
export function* updateProfileItems( items ) {
|
||||||
yield setIsRequesting( 'updateProfileItems', true );
|
yield setIsRequesting( 'updateProfileItems', true );
|
||||||
yield setError( 'updateProfileItems', null );
|
yield setError( 'updateProfileItems', null );
|
||||||
|
|
|
@ -25,6 +25,7 @@ export const defaultState = {
|
||||||
},
|
},
|
||||||
emailPrefill: '',
|
emailPrefill: '',
|
||||||
paymentMethods: [],
|
paymentMethods: [],
|
||||||
|
productTypes: [],
|
||||||
requesting: {},
|
requesting: {},
|
||||||
taskLists: [],
|
taskLists: [],
|
||||||
tasksStatus: {},
|
tasksStatus: {},
|
||||||
|
@ -55,6 +56,7 @@ const onboarding = (
|
||||||
profileItems,
|
profileItems,
|
||||||
emailPrefill,
|
emailPrefill,
|
||||||
paymentMethods,
|
paymentMethods,
|
||||||
|
productTypes,
|
||||||
replace,
|
replace,
|
||||||
error,
|
error,
|
||||||
isRequesting,
|
isRequesting,
|
||||||
|
@ -106,6 +108,19 @@ const onboarding = (
|
||||||
...state,
|
...state,
|
||||||
paymentMethods,
|
paymentMethods,
|
||||||
};
|
};
|
||||||
|
case TYPES.GET_PRODUCT_TYPES_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
productTypes,
|
||||||
|
};
|
||||||
|
case TYPES.GET_PRODUCT_TYPES_ERROR:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
errors: {
|
||||||
|
...state.errors,
|
||||||
|
productTypes: error,
|
||||||
|
},
|
||||||
|
};
|
||||||
case TYPES.GET_FREE_EXTENSIONS_ERROR:
|
case TYPES.GET_FREE_EXTENSIONS_ERROR:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -17,6 +17,8 @@ import {
|
||||||
setTasksStatus,
|
setTasksStatus,
|
||||||
setPaymentMethods,
|
setPaymentMethods,
|
||||||
setEmailPrefill,
|
setEmailPrefill,
|
||||||
|
getProductTypesSuccess,
|
||||||
|
getProductTypesError,
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { DeprecatedTasks } from './deprecated-tasks';
|
import { DeprecatedTasks } from './deprecated-tasks';
|
||||||
|
|
||||||
|
@ -103,3 +105,16 @@ export function* getFreeExtensions() {
|
||||||
yield getFreeExtensionsError( error );
|
yield getFreeExtensionsError( error );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function* getProductTypes() {
|
||||||
|
try {
|
||||||
|
const results = yield apiFetch( {
|
||||||
|
path: WC_ADMIN_NAMESPACE + '/onboarding/product-types',
|
||||||
|
method: 'GET',
|
||||||
|
} );
|
||||||
|
|
||||||
|
yield getProductTypesSuccess( results );
|
||||||
|
} catch ( error ) {
|
||||||
|
yield getProductTypesError( error );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ export const getTasksStatus = (
|
||||||
|
|
||||||
const initialTaskLists: TaskListType[] = [];
|
const initialTaskLists: TaskListType[] = [];
|
||||||
|
|
||||||
|
const EMPTY_ARRAY: Product[] = [];
|
||||||
export const getTaskLists = ( state: OnboardingState ): TaskListType[] => {
|
export const getTaskLists = ( state: OnboardingState ): TaskListType[] => {
|
||||||
return state.taskLists || initialTaskLists;
|
return state.taskLists || initialTaskLists;
|
||||||
};
|
};
|
||||||
|
@ -52,6 +53,10 @@ export const getEmailPrefill = ( state: OnboardingState ): string => {
|
||||||
return state.emailPrefill || '';
|
return state.emailPrefill || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getProductTypes = ( state: OnboardingState ): Product[] => {
|
||||||
|
return state.productTypes || EMPTY_ARRAY;
|
||||||
|
};
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
export type OnboardingSelectors = {
|
export type OnboardingSelectors = {
|
||||||
getProfileItems: () => ReturnType< typeof getProfileItems >;
|
getProfileItems: () => ReturnType< typeof getProfileItems >;
|
||||||
|
@ -69,6 +74,7 @@ export type OnboardingState = {
|
||||||
taskLists: TaskListType[];
|
taskLists: TaskListType[];
|
||||||
tasksStatus: TasksStatusState;
|
tasksStatus: TasksStatusState;
|
||||||
paymentMethods: PaymentMethodsState[];
|
paymentMethods: PaymentMethodsState[];
|
||||||
|
productTypes: Product[];
|
||||||
emailPrefill: string;
|
emailPrefill: string;
|
||||||
// TODO clarify what the error record's type is
|
// TODO clarify what the error record's type is
|
||||||
errors: Record< string, unknown >;
|
errors: Record< string, unknown >;
|
||||||
|
@ -151,6 +157,12 @@ export type MethodFields = {
|
||||||
value?: string;
|
value?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Product = {
|
||||||
|
default?: boolean;
|
||||||
|
label: string;
|
||||||
|
product?: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type PaymentMethodsState = {
|
export type PaymentMethodsState = {
|
||||||
locale: string;
|
locale: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
|
|
@ -76,6 +76,7 @@ class Init {
|
||||||
'Automattic\WooCommerce\Admin\API\Plugins',
|
'Automattic\WooCommerce\Admin\API\Plugins',
|
||||||
'Automattic\WooCommerce\Admin\API\OnboardingFreeExtensions',
|
'Automattic\WooCommerce\Admin\API\OnboardingFreeExtensions',
|
||||||
'Automattic\WooCommerce\Admin\API\OnboardingPayments',
|
'Automattic\WooCommerce\Admin\API\OnboardingPayments',
|
||||||
|
'Automattic\WooCommerce\Admin\API\OnboardingProductTypes',
|
||||||
'Automattic\WooCommerce\Admin\API\OnboardingProfile',
|
'Automattic\WooCommerce\Admin\API\OnboardingProfile',
|
||||||
'Automattic\WooCommerce\Admin\API\OnboardingTasks',
|
'Automattic\WooCommerce\Admin\API\OnboardingTasks',
|
||||||
'Automattic\WooCommerce\Admin\API\OnboardingThemes',
|
'Automattic\WooCommerce\Admin\API\OnboardingThemes',
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* REST API Onboarding Product Types Controller
|
||||||
|
*
|
||||||
|
* Handles requests to /onboarding/product-types
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Admin\API;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Admin\Features\Onboarding;
|
||||||
|
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Onboarding Product Types Controller.
|
||||||
|
*
|
||||||
|
* @extends WC_REST_Data_Controller
|
||||||
|
*/
|
||||||
|
class OnboardingProductTypes extends \WC_REST_Data_Controller {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Endpoint namespace.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $namespace = 'wc-admin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route base.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $rest_base = 'onboarding/product-types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register routes.
|
||||||
|
*/
|
||||||
|
public function register_routes() {
|
||||||
|
register_rest_route(
|
||||||
|
$this->namespace,
|
||||||
|
'/' . $this->rest_base,
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'methods' => \WP_REST_Server::READABLE,
|
||||||
|
'callback' => array( $this, 'get_product_types' ),
|
||||||
|
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||||
|
),
|
||||||
|
'schema' => array( $this, 'get_public_item_schema' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether a given request has permission to read onboarding profile data.
|
||||||
|
*
|
||||||
|
* @param WP_REST_Request $request Full details about the request.
|
||||||
|
* @return WP_Error|boolean
|
||||||
|
*/
|
||||||
|
public function get_items_permissions_check( $request ) {
|
||||||
|
if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) {
|
||||||
|
return new \WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce-admin' ), array( 'status' => rest_authorization_required_code() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return available product types.
|
||||||
|
*
|
||||||
|
* @param \WP_REST_Request $request Request data.
|
||||||
|
*
|
||||||
|
* @return \WP_Error|\WP_REST_Response
|
||||||
|
*/
|
||||||
|
public function get_product_types( $request ) {
|
||||||
|
return Onboarding::get_allowed_product_types();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -461,7 +461,8 @@ class Onboarding {
|
||||||
'product' => 18618,
|
'product' => 18618,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if ( ! Features::is_enabled( 'subscriptions' ) ) {
|
$base_location = wc_get_base_location();
|
||||||
|
if ( ! Features::is_enabled( 'subscriptions' ) || 'US' !== $base_location['country'] ) {
|
||||||
$products['subscriptions']['product'] = 27147;
|
$products['subscriptions']['product'] = 27147;
|
||||||
}
|
}
|
||||||
$product_types = self::append_product_data( $products );
|
$product_types = self::append_product_data( $products );
|
||||||
|
@ -690,7 +691,6 @@ class Onboarding {
|
||||||
$settings['onboarding']['euCountries'] = WC()->countries->get_european_union_countries();
|
$settings['onboarding']['euCountries'] = WC()->countries->get_european_union_countries();
|
||||||
$settings['onboarding']['industries'] = self::get_allowed_industries();
|
$settings['onboarding']['industries'] = self::get_allowed_industries();
|
||||||
$settings['onboarding']['localeInfo'] = include WC()->plugin_path() . '/i18n/locale-info.php';
|
$settings['onboarding']['localeInfo'] = include WC()->plugin_path() . '/i18n/locale-info.php';
|
||||||
$settings['onboarding']['productTypes'] = self::get_allowed_product_types();
|
|
||||||
$settings['onboarding']['profile'] = $profile;
|
$settings['onboarding']['profile'] = $profile;
|
||||||
$settings['onboarding']['themes'] = self::get_themes();
|
$settings['onboarding']['themes'] = self::get_themes();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue