Migrating product editor inventory section to use slot fills (#36509)
Co-authored-by: Lourens Schep <lourensschep@gmail.com>
This commit is contained in:
parent
cb0105efd9
commit
447379a424
|
@ -1,11 +1,14 @@
|
|||
export const PRODUCT_DETAILS_SLUG = 'product-details';
|
||||
|
||||
export const DETAILS_SECTION_ID = 'general/details';
|
||||
export const INVENTORY_SECTION_ID = 'inventory/inventory';
|
||||
export const INVENTORY_SECTION_ADVANCED_ID = 'inventory/advanced';
|
||||
export const IMAGES_SECTION_ID = 'general/images';
|
||||
export const ATTRIBUTES_SECTION_ID = 'general/attributes';
|
||||
export const SHIPPING_SECTION_BASIC_ID = 'shipping/shipping';
|
||||
export const SHIPPING_SECTION_DIMENSIONS_ID = 'shipping/dimensions';
|
||||
|
||||
export const TAB_INVENTORY_ID = 'tab/inventory';
|
||||
export const TAB_GENERAL_ID = 'tab/general';
|
||||
export const TAB_SHIPPING_ID = 'tab/shipping';
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@ export * from './shipping-section/shipping-section-fills';
|
|||
export * from './details-section/details-section-fills';
|
||||
export * from './images-section/images-section-fills';
|
||||
export * from './attributes-section/attributes-section-fills';
|
||||
export * from './inventory-section/inventory-section-fills';
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export * from './inventory-field-sku';
|
||||
export * from './inventory-field-track-quantity';
|
||||
export * from './inventory-field-stock-manual';
|
||||
export * from './inventory-field-stock-manage';
|
||||
export * from './inventory-field-stock-out';
|
||||
export * from './inventory-field-stock-limit';
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useFormContext } from '@woocommerce/components';
|
||||
import { TextControl } from '@wordpress/components';
|
||||
import { Product } from '@woocommerce/data';
|
||||
|
||||
export const InventorySkuField = () => {
|
||||
const { getInputProps } = useFormContext< Product >();
|
||||
|
||||
return (
|
||||
<TextControl
|
||||
label={ __( 'SKU (Stock Keeping Unit)', 'woocommerce' ) }
|
||||
{ ...getInputProps( 'sku', {
|
||||
className: 'half-width-field',
|
||||
} ) }
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useFormContext } from '@woocommerce/components';
|
||||
import { CheckboxControl } from '@wordpress/components';
|
||||
import { Product } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getCheckboxTracks } from '../../sections/utils';
|
||||
|
||||
export const InventoryStockLimitField = () => {
|
||||
const { getCheckboxControlProps } = useFormContext< Product >();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h4>{ __( 'Restrictions', 'woocommerce' ) }</h4>
|
||||
<CheckboxControl
|
||||
label={ __(
|
||||
'Limit purchases to 1 item per order',
|
||||
'woocommerce'
|
||||
) }
|
||||
{ ...getCheckboxControlProps(
|
||||
'sold_individually',
|
||||
getCheckboxTracks( 'sold_individually' )
|
||||
) }
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -2,11 +2,11 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useFormContext, Link } from '@woocommerce/components';
|
||||
import { TextControl } from '@wordpress/components';
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
import interpolateComponents from '@automattic/interpolate-components';
|
||||
import { Link, useFormContext } from '@woocommerce/components';
|
||||
import { Product } from '@woocommerce/data';
|
||||
import interpolateComponents from '@automattic/interpolate-components';
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
|
||||
/**
|
||||
|
@ -14,7 +14,7 @@ import { recordEvent } from '@woocommerce/tracks';
|
|||
*/
|
||||
import { getAdminSetting } from '~/utils/admin-settings';
|
||||
|
||||
export const ManageStockSection: React.FC = () => {
|
||||
export const InventoryStockManageField = () => {
|
||||
const { getInputProps } = useFormContext< Product >();
|
||||
const notifyLowStockAmount = getAdminSetting( 'notifyLowStockAmount', 2 );
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { RadioControl } from '@wordpress/components';
|
||||
import { useFormContext } from '@woocommerce/components';
|
||||
import { RadioControl } from '@wordpress/components';
|
||||
import { Product } from '@woocommerce/data';
|
||||
|
||||
export const ManualStockSection: React.FC = () => {
|
||||
export const InventoryStockManualField = () => {
|
||||
const { getInputProps } = useFormContext< Product >();
|
||||
const inputProps = getInputProps( 'stock_status' );
|
||||
// These properties cause issues with the RadioControl component.
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useFormContext } from '@woocommerce/components';
|
||||
import { RadioControl } from '@wordpress/components';
|
||||
import { Product } from '@woocommerce/data';
|
||||
|
||||
export const InventoryStockOutField = () => {
|
||||
const { getInputProps } = useFormContext< Product >();
|
||||
|
||||
const backordersProp = getInputProps( 'backorders' );
|
||||
// These properties cause issues with the RadioControl component.
|
||||
// A fix to form upstream would help if we can identify what type of input is used.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
delete backordersProp.checked;
|
||||
delete backordersProp.value;
|
||||
|
||||
return (
|
||||
<RadioControl
|
||||
label={ __( 'When out of stock', 'woocommerce' ) }
|
||||
options={ [
|
||||
{
|
||||
label: __( 'Allow purchases', 'woocommerce' ),
|
||||
value: 'yes',
|
||||
},
|
||||
{
|
||||
label: __(
|
||||
'Allow purchases, but notify customers',
|
||||
'woocommerce'
|
||||
),
|
||||
value: 'notify',
|
||||
},
|
||||
{
|
||||
label: __( "Don't allow purchases", 'woocommerce' ),
|
||||
value: 'no',
|
||||
},
|
||||
] }
|
||||
{ ...backordersProp }
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
useFormContext,
|
||||
__experimentalConditionalWrapper as ConditionalWrapper,
|
||||
} from '@woocommerce/components';
|
||||
import { Tooltip, ToggleControl } from '@wordpress/components';
|
||||
import { Product } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getAdminSetting } from '~/utils/admin-settings';
|
||||
import { getCheckboxTracks } from '../../sections/utils';
|
||||
|
||||
export const InventoryTrackQuantityField = () => {
|
||||
const { getCheckboxControlProps } = useFormContext< Product >();
|
||||
|
||||
const canManageStock = getAdminSetting( 'manageStock', 'yes' ) === 'yes';
|
||||
|
||||
return (
|
||||
<ConditionalWrapper
|
||||
condition={ ! canManageStock }
|
||||
wrapper={ ( children: JSX.Element ) => (
|
||||
<Tooltip
|
||||
text={ __(
|
||||
'Quantity tracking is disabled for all products. Go to global store settings to change it.',
|
||||
'woocommerce'
|
||||
) }
|
||||
position="top center"
|
||||
>
|
||||
<div className="woocommerce-product-form__tooltip-disabled-overlay">
|
||||
{ children }
|
||||
</div>
|
||||
</Tooltip>
|
||||
) }
|
||||
>
|
||||
<ToggleControl
|
||||
label={ __( 'Track quantity for this product', 'woocommerce' ) }
|
||||
{ ...getCheckboxControlProps(
|
||||
'manage_stock',
|
||||
getCheckboxTracks( 'manage_stock' )
|
||||
) }
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore This prop does exist, but is not typed in @wordpress/components.
|
||||
disabled={ ! canManageStock }
|
||||
/>
|
||||
</ConditionalWrapper>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
__experimentalWooProductSectionItem as WooProductSectionItem,
|
||||
__experimentalWooProductFieldItem as WooProductFieldItem,
|
||||
__experimentalProductSectionLayout as ProductSectionLayout,
|
||||
Link,
|
||||
useFormContext,
|
||||
CollapsibleContent,
|
||||
} from '@woocommerce/components';
|
||||
import { Card, CardBody } from '@wordpress/components';
|
||||
import { registerPlugin } from '@wordpress/plugins';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
import { Product } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
InventorySkuField,
|
||||
InventoryTrackQuantityField,
|
||||
InventoryStockManualField,
|
||||
InventoryStockManageField,
|
||||
InventoryStockLimitField,
|
||||
InventoryStockOutField,
|
||||
} from './index';
|
||||
import {
|
||||
INVENTORY_SECTION_ID,
|
||||
INVENTORY_SECTION_ADVANCED_ID,
|
||||
TAB_INVENTORY_ID,
|
||||
PLUGIN_ID,
|
||||
} from '../constants';
|
||||
|
||||
const InventorySection = () => {
|
||||
const { values } = useFormContext< Product >();
|
||||
|
||||
return (
|
||||
<>
|
||||
<WooProductSectionItem
|
||||
id={ INVENTORY_SECTION_ID }
|
||||
location={ TAB_INVENTORY_ID }
|
||||
pluginId={ PLUGIN_ID }
|
||||
order={ 1 }
|
||||
>
|
||||
<ProductSectionLayout
|
||||
title={ __( 'Inventory', 'woocommerce' ) }
|
||||
description={
|
||||
<>
|
||||
<span>
|
||||
{ __(
|
||||
'Set up and manage inventory for this product, including status and available quantity.',
|
||||
'woocommerce'
|
||||
) }
|
||||
</span>
|
||||
<Link
|
||||
href={ getAdminLink(
|
||||
'admin.php?page=wc-settings&tab=products§ion=inventory'
|
||||
) }
|
||||
target="_blank"
|
||||
type="wp-admin"
|
||||
onClick={ () => {
|
||||
recordEvent( 'add_product_inventory_help' );
|
||||
} }
|
||||
className="woocommerce-form-section__header-link"
|
||||
>
|
||||
{ __(
|
||||
'Manage global inventory settings',
|
||||
'woocommerce'
|
||||
) }
|
||||
</Link>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<WooProductFieldItem.Slot
|
||||
section={ INVENTORY_SECTION_ID }
|
||||
/>
|
||||
<CollapsibleContent
|
||||
toggleText={ __( 'Advanced', 'woocommerce' ) }
|
||||
>
|
||||
<WooProductFieldItem.Slot
|
||||
section={ INVENTORY_SECTION_ADVANCED_ID }
|
||||
/>
|
||||
</CollapsibleContent>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</ProductSectionLayout>
|
||||
</WooProductSectionItem>
|
||||
<WooProductFieldItem
|
||||
id="inventory/sku"
|
||||
section={ INVENTORY_SECTION_ID }
|
||||
pluginId={ PLUGIN_ID }
|
||||
order={ 1 }
|
||||
>
|
||||
<InventorySkuField />
|
||||
</WooProductFieldItem>
|
||||
<WooProductFieldItem
|
||||
id="inventory/track-quantity"
|
||||
section={ INVENTORY_SECTION_ID }
|
||||
pluginId={ PLUGIN_ID }
|
||||
order={ 3 }
|
||||
>
|
||||
<InventoryTrackQuantityField />
|
||||
</WooProductFieldItem>
|
||||
|
||||
{ values.manage_stock ? (
|
||||
<WooProductFieldItem
|
||||
id="inventory/stock-manage"
|
||||
section={ INVENTORY_SECTION_ID }
|
||||
pluginId={ PLUGIN_ID }
|
||||
order={ 5 }
|
||||
>
|
||||
<InventoryStockManageField />
|
||||
</WooProductFieldItem>
|
||||
) : (
|
||||
<WooProductFieldItem
|
||||
id="inventory/stock-manual"
|
||||
section={ INVENTORY_SECTION_ID }
|
||||
pluginId={ PLUGIN_ID }
|
||||
order={ 5 }
|
||||
>
|
||||
<InventoryStockManualField />
|
||||
</WooProductFieldItem>
|
||||
) }
|
||||
|
||||
{ values.manage_stock && (
|
||||
<WooProductFieldItem
|
||||
id="inventory/advanced/stock-out"
|
||||
section={ INVENTORY_SECTION_ADVANCED_ID }
|
||||
pluginId={ PLUGIN_ID }
|
||||
order={ 1 }
|
||||
>
|
||||
<InventoryStockOutField />
|
||||
</WooProductFieldItem>
|
||||
) }
|
||||
|
||||
<WooProductFieldItem
|
||||
id="inventory/advanced/stock-limit"
|
||||
section={ INVENTORY_SECTION_ADVANCED_ID }
|
||||
pluginId={ PLUGIN_ID }
|
||||
order={ 3 }
|
||||
>
|
||||
<InventoryStockLimitField />
|
||||
</WooProductFieldItem>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
registerPlugin( 'wc-admin-product-editor-inventory-section', {
|
||||
// @ts-expect-error 'scope' does exist. @types/wordpress__plugins is outdated.
|
||||
scope: 'woocommerce-product-editor',
|
||||
render: () => <InventorySection />,
|
||||
} );
|
|
@ -16,14 +16,17 @@ import { Ref } from 'react';
|
|||
*/
|
||||
import { ProductFormHeader } from './layout/product-form-header';
|
||||
import { ProductFormLayout } from './layout/product-form-layout';
|
||||
import { ProductInventorySection } from './sections/product-inventory-section';
|
||||
import { PricingSection } from './sections/pricing-section';
|
||||
import { ProductVariationsSection } from './sections/product-variations-section';
|
||||
import { validate } from './product-validation';
|
||||
import { OptionsSection } from './sections/options-section';
|
||||
import { ProductFormFooter } from './layout/product-form-footer';
|
||||
import { ProductFormTab } from './product-form-tab';
|
||||
import { TAB_GENERAL_ID, TAB_SHIPPING_ID } from './fills/constants';
|
||||
import {
|
||||
TAB_GENERAL_ID,
|
||||
TAB_SHIPPING_ID,
|
||||
TAB_INVENTORY_ID,
|
||||
} from './fills/constants';
|
||||
|
||||
export const ProductForm: React.FC< {
|
||||
product?: PartialProduct;
|
||||
|
@ -64,7 +67,9 @@ export const ProductForm: React.FC< {
|
|||
title="Inventory"
|
||||
disabled={ !! product?.variations?.length }
|
||||
>
|
||||
<ProductInventorySection />
|
||||
<WooProductSectionItem.Slot
|
||||
location={ TAB_INVENTORY_ID }
|
||||
/>
|
||||
</ProductFormTab>
|
||||
<ProductFormTab
|
||||
name="shipping"
|
||||
|
|
|
@ -11,10 +11,28 @@ import {
|
|||
import type { FormErrors } from '@woocommerce/components';
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { validate as validateInventory } from './sections/product-inventory-section';
|
||||
const validateInventory = (
|
||||
values: Partial< Product< ProductStatus, ProductType > >,
|
||||
errors: FormErrors< typeof values >
|
||||
) => {
|
||||
const nextErrors = { ...errors };
|
||||
|
||||
if ( values.stock_quantity && values.stock_quantity < 0 ) {
|
||||
nextErrors.stock_quantity = __(
|
||||
'Stock quantity must be a positive number.',
|
||||
'woocommerce'
|
||||
);
|
||||
}
|
||||
|
||||
if ( values.low_stock_amount && values.low_stock_amount < 0 ) {
|
||||
nextErrors.low_stock_amount = __(
|
||||
'Stock quantity must be a positive number.',
|
||||
'woocommerce'
|
||||
);
|
||||
}
|
||||
|
||||
return nextErrors;
|
||||
};
|
||||
|
||||
function validateScheduledSaleFields(
|
||||
values: Partial< Product< ProductStatus, ProductType > >
|
||||
|
|
|
@ -20,11 +20,10 @@ import { ProductFormLayout } from './layout/product-form-layout';
|
|||
import { ProductFormFooter } from './layout/product-form-footer';
|
||||
import { ProductFormTab } from './product-form-tab';
|
||||
import { PricingSection } from './sections/pricing-section';
|
||||
import { ProductInventorySection } from './sections/product-inventory-section';
|
||||
import { ProductVariationDetailsSection } from './sections/product-variation-details-section';
|
||||
import { ProductVariationFormHeader } from './layout/product-variation-form-header';
|
||||
import useProductVariationNavigation from './hooks/use-product-variation-navigation';
|
||||
import { TAB_SHIPPING_ID } from './fills/constants';
|
||||
import { TAB_INVENTORY_ID, TAB_SHIPPING_ID } from './fills/constants';
|
||||
|
||||
import './product-variation-form.scss';
|
||||
|
||||
|
@ -66,7 +65,9 @@ export const ProductVariationForm: React.FC< {
|
|||
<PricingSection />
|
||||
</ProductFormTab>
|
||||
<ProductFormTab name="inventory" title="Inventory">
|
||||
<ProductInventorySection />
|
||||
<WooProductSectionItem.Slot
|
||||
location={ TAB_INVENTORY_ID }
|
||||
/>
|
||||
</ProductFormTab>
|
||||
<ProductFormTab name="shipping" title="Shipping">
|
||||
<WooProductSectionItem.Slot
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { CheckboxControl, RadioControl } from '@wordpress/components';
|
||||
import { Product } from '@woocommerce/data';
|
||||
import { useFormContext } from '@woocommerce/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getCheckboxTracks } from '../utils';
|
||||
|
||||
export const AdvancedStockSection: React.FC = () => {
|
||||
const { getCheckboxControlProps, getInputProps, values } =
|
||||
useFormContext< Product >();
|
||||
|
||||
const backordersProp = getInputProps( 'backorders' );
|
||||
// These properties cause issues with the RadioControl component.
|
||||
// A fix to form upstream would help if we can identify what type of input is used.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
delete backordersProp.checked;
|
||||
delete backordersProp.value;
|
||||
|
||||
return (
|
||||
<>
|
||||
{ values.manage_stock && (
|
||||
<RadioControl
|
||||
label={ __( 'When out of stock', 'woocommerce' ) }
|
||||
options={ [
|
||||
{
|
||||
label: __( 'Allow purchases', 'woocommerce' ),
|
||||
value: 'yes',
|
||||
},
|
||||
{
|
||||
label: __(
|
||||
'Allow purchases, but notify customers',
|
||||
'woocommerce'
|
||||
),
|
||||
value: 'notify',
|
||||
},
|
||||
{
|
||||
label: __( "Don't allow purchases", 'woocommerce' ),
|
||||
value: 'no',
|
||||
},
|
||||
] }
|
||||
{ ...backordersProp }
|
||||
/>
|
||||
) }
|
||||
<h4>{ __( 'Restrictions', 'woocommerce' ) }</h4>
|
||||
<CheckboxControl
|
||||
label={ __(
|
||||
'Limit purchases to 1 item per order',
|
||||
'woocommerce'
|
||||
) }
|
||||
{ ...getCheckboxControlProps(
|
||||
'sold_individually',
|
||||
getCheckboxTracks( 'sold_individually' )
|
||||
) }
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,2 +0,0 @@
|
|||
export * from './product-inventory-section';
|
||||
export * from './utils';
|
|
@ -1,124 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
CollapsibleContent,
|
||||
__experimentalConditionalWrapper as ConditionalWrapper,
|
||||
Link,
|
||||
useFormContext,
|
||||
} from '@woocommerce/components';
|
||||
import {
|
||||
Card,
|
||||
CardBody,
|
||||
ToggleControl,
|
||||
TextControl,
|
||||
Tooltip,
|
||||
} from '@wordpress/components';
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
import { Product } from '@woocommerce/data';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { AdvancedStockSection } from './advanced-stock-section';
|
||||
import { getCheckboxTracks } from '../utils';
|
||||
import { getAdminSetting } from '~/utils/admin-settings';
|
||||
import { ProductSectionLayout } from '../../layout/product-section-layout';
|
||||
import { ManageStockSection } from './manage-stock-section';
|
||||
import { ManualStockSection } from './manual-stock-section';
|
||||
|
||||
export const ProductInventorySection: React.FC = () => {
|
||||
const { getCheckboxControlProps, getInputProps, values } =
|
||||
useFormContext< Product >();
|
||||
const canManageStock = getAdminSetting( 'manageStock', 'yes' ) === 'yes';
|
||||
|
||||
return (
|
||||
<ProductSectionLayout
|
||||
title={ __( 'Inventory', 'woocommerce' ) }
|
||||
description={
|
||||
<>
|
||||
<span>
|
||||
{ __(
|
||||
'Set up and manage inventory for this product, including status and available quantity.',
|
||||
'woocommerce'
|
||||
) }
|
||||
</span>
|
||||
<Link
|
||||
href={ getAdminLink(
|
||||
'admin.php?page=wc-settings&tab=products§ion=inventory'
|
||||
) }
|
||||
target="_blank"
|
||||
type="wp-admin"
|
||||
onClick={ () => {
|
||||
recordEvent( 'add_product_inventory_help' );
|
||||
} }
|
||||
className="woocommerce-form-section__header-link"
|
||||
>
|
||||
{ __(
|
||||
'Manage global inventory settings',
|
||||
'woocommerce'
|
||||
) }
|
||||
</Link>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<TextControl
|
||||
label={ __(
|
||||
'SKU (Stock Keeping Unit)',
|
||||
'woocommerce'
|
||||
) }
|
||||
{ ...getInputProps( 'sku', {
|
||||
className: 'half-width-field',
|
||||
} ) }
|
||||
/>
|
||||
<div className="woocommerce-product-form__field">
|
||||
<ConditionalWrapper
|
||||
condition={ ! canManageStock }
|
||||
wrapper={ ( children: JSX.Element ) => (
|
||||
<Tooltip
|
||||
text={ __(
|
||||
'Quantity tracking is disabled for all products. Go to global store settings to change it.',
|
||||
'woocommerce'
|
||||
) }
|
||||
position="top center"
|
||||
>
|
||||
<div className="woocommerce-product-form__tooltip-disabled-overlay">
|
||||
{ children }
|
||||
</div>
|
||||
</Tooltip>
|
||||
) }
|
||||
>
|
||||
<ToggleControl
|
||||
label={ __(
|
||||
'Track quantity for this product',
|
||||
'woocommerce'
|
||||
) }
|
||||
{ ...getCheckboxControlProps(
|
||||
'manage_stock',
|
||||
getCheckboxTracks( 'manage_stock' )
|
||||
) }
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore This prop does exist, but is not typed in @wordpress/components.
|
||||
disabled={ ! canManageStock }
|
||||
/>
|
||||
</ConditionalWrapper>
|
||||
</div>
|
||||
{ values.manage_stock ? (
|
||||
<ManageStockSection />
|
||||
) : (
|
||||
<ManualStockSection />
|
||||
) }
|
||||
<CollapsibleContent
|
||||
toggleText={ __( 'Advanced', 'woocommerce' ) }
|
||||
>
|
||||
<AdvancedStockSection />
|
||||
</CollapsibleContent>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</ProductSectionLayout>
|
||||
);
|
||||
};
|
|
@ -1,29 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { ProductStatus, ProductType, Product } from '@woocommerce/data';
|
||||
import type { FormErrors } from '@woocommerce/components';
|
||||
|
||||
export const validate = (
|
||||
values: Partial< Product< ProductStatus, ProductType > >,
|
||||
errors: FormErrors< typeof values >
|
||||
) => {
|
||||
const nextErrors = { ...errors };
|
||||
|
||||
if ( values.stock_quantity && values.stock_quantity < 0 ) {
|
||||
nextErrors.stock_quantity = __(
|
||||
'Stock quantity must be a positive number.',
|
||||
'woocommerce'
|
||||
);
|
||||
}
|
||||
|
||||
if ( values.low_stock_amount && values.low_stock_amount < 0 ) {
|
||||
nextErrors.low_stock_amount = __(
|
||||
'Stock quantity must be a positive number.',
|
||||
'woocommerce'
|
||||
);
|
||||
}
|
||||
|
||||
return nextErrors;
|
||||
};
|
|
@ -10,14 +10,16 @@ import userEvent from '@testing-library/user-event';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { getAdminSetting } from '~/utils/admin-settings';
|
||||
import { ProductInventorySection } from '../';
|
||||
//import { ProductInventorySection } from '../product-inventory-section';
|
||||
|
||||
jest.mock( '@woocommerce/tracks', () => ( { recordEvent: jest.fn() } ) );
|
||||
jest.mock( '~/utils/admin-settings', () => ( {
|
||||
getAdminSetting: jest.fn(),
|
||||
} ) );
|
||||
|
||||
describe( 'ProductInventorySection', () => {
|
||||
const ProductInventorySection = () => <div>Mock inventory</div>;
|
||||
|
||||
describe.skip( 'ProductInventorySection', () => {
|
||||
beforeEach( () => {
|
||||
jest.clearAllMocks();
|
||||
( getAdminSetting as jest.Mock ).mockImplementation(
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Migrating product editor inventory section to slot fills.
|
Loading…
Reference in New Issue