Add reorder grouped products option (#42766)
* Add re-order modal * Consolidate some of the styling and components * Add changelog * Only show reorder when products are added, and remove 'x' from reorder modal
This commit is contained in:
parent
3042b9fba6
commit
b406a084e4
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: update
|
||||||
|
|
||||||
|
Update products list field to add re-order option.
|
|
@ -24,6 +24,7 @@ import classNames from 'classnames';
|
||||||
import {
|
import {
|
||||||
AddProductsModal,
|
AddProductsModal,
|
||||||
getProductImageStyle,
|
getProductImageStyle,
|
||||||
|
ReorderProductsModal,
|
||||||
} from '../../../components/add-products-modal';
|
} from '../../../components/add-products-modal';
|
||||||
import { ProductEditorBlockEditProps } from '../../../types';
|
import { ProductEditorBlockEditProps } from '../../../types';
|
||||||
import { Shirt, Pants, Glasses } from './images';
|
import { Shirt, Pants, Glasses } from './images';
|
||||||
|
@ -40,6 +41,8 @@ export function Edit( {
|
||||||
const { property } = attributes;
|
const { property } = attributes;
|
||||||
const blockProps = useWooBlockProps( attributes );
|
const blockProps = useWooBlockProps( attributes );
|
||||||
const [ openAddProductsModal, setOpenAddProductsModal ] = useState( false );
|
const [ openAddProductsModal, setOpenAddProductsModal ] = useState( false );
|
||||||
|
const [ openReorderProductsModal, setOpenReorderProductsModal ] =
|
||||||
|
useState( false );
|
||||||
const [ isLoading, setIsLoading ] = useState( false );
|
const [ isLoading, setIsLoading ] = useState( false );
|
||||||
const [ preventFetch, setPreventFetch ] = useState( false );
|
const [ preventFetch, setPreventFetch ] = useState( false );
|
||||||
const [ groupedProductIds, setGroupedProductIds ] = useEntityProp<
|
const [ groupedProductIds, setGroupedProductIds ] = useEntityProp<
|
||||||
|
@ -72,6 +75,10 @@ export function Edit( {
|
||||||
setOpenAddProductsModal( true );
|
setOpenAddProductsModal( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleReorderProductsButtonClick() {
|
||||||
|
setOpenReorderProductsModal( true );
|
||||||
|
}
|
||||||
|
|
||||||
function handleAddProductsModalSubmit( value: Product[] ) {
|
function handleAddProductsModalSubmit( value: Product[] ) {
|
||||||
const newGroupedProducts = [ ...groupedProducts, ...value ];
|
const newGroupedProducts = [ ...groupedProducts, ...value ];
|
||||||
setPreventFetch( true );
|
setPreventFetch( true );
|
||||||
|
@ -82,10 +89,20 @@ export function Edit( {
|
||||||
setOpenAddProductsModal( false );
|
setOpenAddProductsModal( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleReorderProductsModalSubmit( value: Product[] ) {
|
||||||
|
setGroupedProducts( value );
|
||||||
|
setGroupedProductIds( value.map( ( product ) => product.id ) );
|
||||||
|
setOpenReorderProductsModal( false );
|
||||||
|
}
|
||||||
|
|
||||||
function handleAddProductsModalClose() {
|
function handleAddProductsModalClose() {
|
||||||
setOpenAddProductsModal( false );
|
setOpenAddProductsModal( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleReorderProductsModalClose() {
|
||||||
|
setOpenReorderProductsModal( false );
|
||||||
|
}
|
||||||
|
|
||||||
function removeProductHandler( product: Product ) {
|
function removeProductHandler( product: Product ) {
|
||||||
return function handleRemoveClick() {
|
return function handleRemoveClick() {
|
||||||
const newGroupedProducts = groupedProducts.filter(
|
const newGroupedProducts = groupedProducts.filter(
|
||||||
|
@ -104,6 +121,14 @@ export function Edit( {
|
||||||
return (
|
return (
|
||||||
<div { ...blockProps }>
|
<div { ...blockProps }>
|
||||||
<div className="wp-block-woocommerce-product-list-field__header">
|
<div className="wp-block-woocommerce-product-list-field__header">
|
||||||
|
{ ! isLoading && groupedProducts.length > 0 && (
|
||||||
|
<Button
|
||||||
|
onClick={ handleReorderProductsButtonClick }
|
||||||
|
variant="tertiary"
|
||||||
|
>
|
||||||
|
{ __( 'Reorder', 'woocommerce' ) }
|
||||||
|
</Button>
|
||||||
|
) }
|
||||||
<Button
|
<Button
|
||||||
onClick={ handleAddProductsButtonClick }
|
onClick={ handleAddProductsButtonClick }
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
@ -294,6 +319,13 @@ export function Edit( {
|
||||||
onClose={ handleAddProductsModalClose }
|
onClose={ handleAddProductsModalClose }
|
||||||
/>
|
/>
|
||||||
) }
|
) }
|
||||||
|
{ openReorderProductsModal && (
|
||||||
|
<ReorderProductsModal
|
||||||
|
products={ groupedProducts }
|
||||||
|
onSubmit={ handleReorderProductsModalSubmit }
|
||||||
|
onClose={ handleReorderProductsModalClose }
|
||||||
|
/>
|
||||||
|
) }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
|
gap: $gap-smaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__empty-state {
|
&__empty-state {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
useState,
|
useState,
|
||||||
} from '@wordpress/element';
|
} from '@wordpress/element';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { closeSmall, dragHandle } from '@wordpress/icons';
|
import { closeSmall } from '@wordpress/icons';
|
||||||
import {
|
import {
|
||||||
__experimentalSelectControl as SelectControl,
|
__experimentalSelectControl as SelectControl,
|
||||||
__experimentalSelectControlMenu as Menu,
|
__experimentalSelectControlMenu as Menu,
|
||||||
|
@ -21,13 +21,11 @@ import {
|
||||||
} from '@woocommerce/components';
|
} from '@woocommerce/components';
|
||||||
import { CurrencyContext } from '@woocommerce/currency';
|
import { CurrencyContext } from '@woocommerce/currency';
|
||||||
import { PRODUCTS_STORE_NAME, Product } from '@woocommerce/data';
|
import { PRODUCTS_STORE_NAME, Product } from '@woocommerce/data';
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { AddProductsModalProps } from './types';
|
import { AddProductsModalProps } from './types';
|
||||||
import { useDraggable } from '../../hooks/use-draggable';
|
|
||||||
|
|
||||||
export function getProductImageStyle( product: Product ) {
|
export function getProductImageStyle( product: Product ) {
|
||||||
return product.images.length > 0
|
return product.images.length > 0
|
||||||
|
@ -103,10 +101,6 @@ export function AddProductsModal( {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { container, draggable, handler } = useDraggable( {
|
|
||||||
onSort: setSelectedProducts,
|
|
||||||
} );
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={ __( 'Add products to this group', 'woocommerce' ) }
|
title={ __( 'Add products to this group', 'woocommerce' ) }
|
||||||
|
@ -204,29 +198,12 @@ export function AddProductsModal( {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ Boolean( selectedProducts.length ) && (
|
{ Boolean( selectedProducts.length ) && (
|
||||||
<ul
|
<ul className="woocommerce-add-products-modal__list">
|
||||||
{ ...container }
|
|
||||||
className={ classNames(
|
|
||||||
'woocommerce-add-products-modal__list',
|
|
||||||
container.className
|
|
||||||
) }
|
|
||||||
>
|
|
||||||
{ selectedProducts.map( ( item ) => (
|
{ selectedProducts.map( ( item ) => (
|
||||||
<li
|
<li
|
||||||
{ ...draggable }
|
|
||||||
key={ item.id }
|
key={ item.id }
|
||||||
className="woocommerce-add-products-modal__list-item"
|
className="woocommerce-add-products-modal__list-item"
|
||||||
>
|
>
|
||||||
<Button
|
|
||||||
{ ...handler }
|
|
||||||
icon={ dragHandle }
|
|
||||||
variant="tertiary"
|
|
||||||
type="button"
|
|
||||||
aria-label={ __(
|
|
||||||
'Sortable handler',
|
|
||||||
'woocommerce'
|
|
||||||
) }
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
className="woocommerce-add-products-modal__list-item-image"
|
className="woocommerce-add-products-modal__list-item-image"
|
||||||
style={ getProductImageStyle( item ) }
|
style={ getProductImageStyle( item ) }
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export * from './add-products-modal';
|
export * from './add-products-modal';
|
||||||
|
export * from './reorder-products-modal';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { FormEvent } from 'react';
|
||||||
|
import { Button, Modal } from '@wordpress/components';
|
||||||
|
import { createElement, useState } from '@wordpress/element';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { dragHandle } from '@wordpress/icons';
|
||||||
|
import { Product } from '@woocommerce/data';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { ReorderProductsModalProps } from './types';
|
||||||
|
import { useDraggable } from '../../hooks/use-draggable';
|
||||||
|
import { getProductImageStyle } from './add-products-modal';
|
||||||
|
|
||||||
|
export function ReorderProductsModal( {
|
||||||
|
products,
|
||||||
|
onSubmit,
|
||||||
|
onClose,
|
||||||
|
}: ReorderProductsModalProps ) {
|
||||||
|
const [ selectedProducts, setSelectedProducts ] = useState< Product[] >( [
|
||||||
|
...products,
|
||||||
|
] );
|
||||||
|
|
||||||
|
function handleSubmit( event: FormEvent< HTMLFormElement > ) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
onSubmit( [ ...selectedProducts ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCancelClick() {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { container, draggable, handler } = useDraggable( {
|
||||||
|
onSort: setSelectedProducts,
|
||||||
|
} );
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={ __( 'Reorder products in this group', 'woocommerce' ) }
|
||||||
|
className="woocommerce-reorder-products-modal"
|
||||||
|
onRequestClose={ onClose }
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
noValidate
|
||||||
|
onSubmit={ handleSubmit }
|
||||||
|
className="woocommerce-add-products-modal__form"
|
||||||
|
>
|
||||||
|
<fieldset className="woocommerce-add-products-modal__form-group">
|
||||||
|
<legend className="woocommerce-add-products-modal__form-group-title">
|
||||||
|
{ __(
|
||||||
|
'Click and drag to reorder on the product page.',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
</legend>
|
||||||
|
|
||||||
|
{ Boolean( selectedProducts.length ) && (
|
||||||
|
<ul
|
||||||
|
{ ...container }
|
||||||
|
className={ classNames(
|
||||||
|
'woocommerce-add-products-modal__list',
|
||||||
|
container.className
|
||||||
|
) }
|
||||||
|
>
|
||||||
|
{ selectedProducts.map( ( item ) => (
|
||||||
|
<li
|
||||||
|
{ ...draggable }
|
||||||
|
key={ item.id }
|
||||||
|
className="woocommerce-add-products-modal__list-item"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
{ ...handler }
|
||||||
|
icon={ dragHandle }
|
||||||
|
variant="tertiary"
|
||||||
|
type="button"
|
||||||
|
aria-label={ __(
|
||||||
|
'Sortable handler',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="woocommerce-add-products-modal__list-item-image"
|
||||||
|
style={ getProductImageStyle( item ) }
|
||||||
|
/>
|
||||||
|
<div className="woocommerce-add-products-modal__list-item-content">
|
||||||
|
<div className="woocommerce-add-products-modal__list-item-title">
|
||||||
|
{ item.name }
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="woocommerce-add-products-modal__list-item-description">
|
||||||
|
{ item.sku }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
) ) }
|
||||||
|
</ul>
|
||||||
|
) }
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div className="woocommerce-add-products-modal__actions">
|
||||||
|
<Button
|
||||||
|
variant="tertiary"
|
||||||
|
type="button"
|
||||||
|
onClick={ handleCancelClick }
|
||||||
|
>
|
||||||
|
{ __( 'Cancel', 'woocommerce' ) }
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" type="submit">
|
||||||
|
{ __( 'Done', 'woocommerce' ) }
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
.woocommerce-add-products-modal {
|
.woocommerce-add-products-modal,
|
||||||
|
.woocommerce-reorder-products-modal {
|
||||||
@include breakpoint(">600px") {
|
@include breakpoint(">600px") {
|
||||||
width: calc(100% - 32px);
|
width: calc(100% - 32px);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { Product } from '@woocommerce/data';
|
import type { Product } from '@woocommerce/data';
|
||||||
|
|
||||||
export type AddProductsModalProps = {
|
export type AddProductsModalProps = {
|
||||||
initialValue: Product[];
|
initialValue: Product[];
|
||||||
onSubmit( value: Product[] ): void;
|
onSubmit( value: Product[] ): void;
|
||||||
onClose(): void;
|
onClose(): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ReorderProductsModalProps = {
|
||||||
|
products: Product[];
|
||||||
|
onSubmit( value: Product[] ): void;
|
||||||
|
onClose(): void;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue