diff --git a/packages/js/product-editor/changelog/add-inventory-sku-block-37399 b/packages/js/product-editor/changelog/add-inventory-sku-block-37399 new file mode 100644 index 00000000000..c6141801e2a --- /dev/null +++ b/packages/js/product-editor/changelog/add-inventory-sku-block-37399 @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Adding sku block to product editor. diff --git a/packages/js/product-editor/src/blocks/inventory-sku/block.json b/packages/js/product-editor/src/blocks/inventory-sku/block.json new file mode 100644 index 00000000000..335c9de9858 --- /dev/null +++ b/packages/js/product-editor/src/blocks/inventory-sku/block.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "woocommerce/product-sku", + "title": "Product text control", + "category": "woocommerce", + "description": "The product sku.", + "keywords": [ "products", "sku" ], + "textdomain": "default", + "attributes": { + "name": { + "type": "string", + "__experimentalRole": "content" + } + }, + "supports": { + "align": false, + "html": false, + "multiple": true, + "reusable": false, + "inserter": false, + "lock": false, + "__experimentalToolbar": false + }, + "editorStyle": "file:./editor.css" +} diff --git a/packages/js/product-editor/src/blocks/inventory-sku/edit.tsx b/packages/js/product-editor/src/blocks/inventory-sku/edit.tsx new file mode 100644 index 00000000000..9c4519a986c --- /dev/null +++ b/packages/js/product-editor/src/blocks/inventory-sku/edit.tsx @@ -0,0 +1,51 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { createElement, createInterpolateElement } from '@wordpress/element'; +import { useBlockProps } from '@wordpress/block-editor'; + +import { + BaseControl, + // @ts-expect-error `__experimentalInputControl` does exist. + __experimentalInputControl as InputControl, +} from '@wordpress/components'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore No types for this exist yet. +// eslint-disable-next-line @woocommerce/dependency-group +import { useEntityProp } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ + +export function Edit() { + const blockProps = useBlockProps(); + + const [ sku, setSku ] = useEntityProp( 'postType', 'product', 'sku' ); + + return ( +
+ ', 'woocommerce' ), + { + description: ( + + { __( '(STOCK KEEPING UNIT)', 'woocommerce' ) } + + ), + } + ) } + > + + +
+ ); +} diff --git a/packages/js/product-editor/src/blocks/inventory-sku/index.ts b/packages/js/product-editor/src/blocks/inventory-sku/index.ts new file mode 100644 index 00000000000..15144b2b28d --- /dev/null +++ b/packages/js/product-editor/src/blocks/inventory-sku/index.ts @@ -0,0 +1,17 @@ +/** + * Internal dependencies + */ +import initBlock from '../../utils/init-block'; +import metadata from './block.json'; +import { Edit } from './edit'; + +const { name } = metadata; + +export { metadata, name }; + +export const settings = { + example: {}, + edit: Edit, +}; + +export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/js/product-editor/src/blocks/inventory-sku/style.scss b/packages/js/product-editor/src/blocks/inventory-sku/style.scss new file mode 100644 index 00000000000..32372ce5b82 --- /dev/null +++ b/packages/js/product-editor/src/blocks/inventory-sku/style.scss @@ -0,0 +1,13 @@ + +.woocommerce-product-form_inventory-sku { + .components-base-control__label { + display: flex; + align-items: center; + } + .woocommerce-product-form__optional-input { + margin-left: $gap-smallest; + } + .woocommerce-tooltip__button { + padding: 0 0 0 $gap-smallest; + } +} diff --git a/packages/js/product-editor/src/components/details-name-block/edit.tsx b/packages/js/product-editor/src/components/details-name-block/edit.tsx index ee06d15d53b..a06c2de2d9a 100644 --- a/packages/js/product-editor/src/components/details-name-block/edit.tsx +++ b/packages/js/product-editor/src/components/details-name-block/edit.tsx @@ -33,6 +33,7 @@ import { useEntityProp, useEntityId } from '@wordpress/core-data'; */ import { AUTO_DRAFT_NAME } from '../../utils'; import { EditProductLinkModal } from '../edit-product-link-modal'; + import { useValidation } from '../../hooks/use-validation'; export function Edit() { @@ -52,6 +53,7 @@ export function Edit() { ) ); + const [ sku, setSku ] = useEntityProp( 'postType', 'product', 'sku' ); const [ name, setName ] = useEntityProp< string >( 'postType', 'product', @@ -79,6 +81,13 @@ export function Edit() { () => Boolean( name ) && name !== AUTO_DRAFT_NAME ); + const setSkuIfEmpty = () => { + if ( sku || ! nameIsValid ) { + return; + } + setSku( cleanForSlug( name ) ); + }; + return ( <>
@@ -103,6 +112,7 @@ export function Edit() { ) } onChange={ setName } value={ name || '' } + onBlur={ setSkuIfEmpty } /> { productId && diff --git a/packages/js/product-editor/src/components/editor/init-blocks.ts b/packages/js/product-editor/src/components/editor/init-blocks.ts index ea4d0128b1d..8eef2638b22 100644 --- a/packages/js/product-editor/src/components/editor/init-blocks.ts +++ b/packages/js/product-editor/src/components/editor/init-blocks.ts @@ -22,6 +22,7 @@ import { init as initPricing } from '../pricing-block'; import { init as initCollapsible } from '../collapsible-block'; import { init as initScheduleSale } from '../../blocks/schedule-sale'; import { init as initTrackInventory } from '../../blocks/track-inventory'; +import { init as initSku } from '../../blocks/inventory-sku'; export const initBlocks = () => { const coreBlocks = __experimentalGetCoreBlocks(); @@ -42,4 +43,5 @@ export const initBlocks = () => { initCollapsible(); initScheduleSale(); initTrackInventory(); + initSku(); }; diff --git a/packages/js/product-editor/src/style.scss b/packages/js/product-editor/src/style.scss index 6decb51c153..e263448c1bc 100644 --- a/packages/js/product-editor/src/style.scss +++ b/packages/js/product-editor/src/style.scss @@ -16,3 +16,4 @@ @import 'components/product-mvp-ces-footer/style.scss'; @import 'components/product-mvp-feedback-modal/style.scss'; @import 'components/details-name-block/style.scss'; +@import 'blocks/inventory-sku/style.scss'; diff --git a/plugins/woocommerce/changelog/add-inventory-sku-block-37399 b/plugins/woocommerce/changelog/add-inventory-sku-block-37399 new file mode 100644 index 00000000000..07efb4ad5cb --- /dev/null +++ b/plugins/woocommerce/changelog/add-inventory-sku-block-37399 @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Adding inventory section and sku blocks to product block editor. diff --git a/plugins/woocommerce/includes/class-wc-post-types.php b/plugins/woocommerce/includes/class-wc-post-types.php index a115f340190..bad5ec26790 100644 --- a/plugins/woocommerce/includes/class-wc-post-types.php +++ b/plugins/woocommerce/includes/class-wc-post-types.php @@ -585,10 +585,30 @@ class WC_Post_Types { ), array( array( - 'woocommerce/product-track-inventory-fields', - array(), + 'woocommerce/product-section', + array( + 'title' => __( 'Inventory', 'woocommerce' ), + 'description' => sprintf( + /* translators: %1$s: Inventory settings link opening tag. %2$s: Inventory settings link closing tag.*/ + __( 'Set up and manage inventory for this product, including status and available quantity. %1$sManage store inventory settings%2$s', 'woocommerce' ), + '', + '' + ), + 'icon' => array( + 'src' => '', + ), + ), + array( + array( + 'woocommerce/product-sku', + ), + array( + 'woocommerce/product-track-inventory-fields', + ), + ), ), ), + ), array( 'woocommerce/product-tab', @@ -600,7 +620,7 @@ class WC_Post_Types { array( 'woocommerce/product-section', array( - 'title' => __( 'Shipping section', 'woocommerce' ), + 'title' => __( 'Shipping', 'woocommerce' ), 'icon' => array( 'src' => '', ),