[Product Block Editor]: implement `Choose products for me` button (#43520)
* implement `Choose products for me` button * clean * selectSearchedProductDispatcher accepts products array * rename component with LinkedProductListBlockEdit * pull and set linked products from choose button * changelog * rollback minor changes * fix typo in fn * pull the related product from core entities * minor
This commit is contained in:
parent
9ce508f47d
commit
47e1f50ae2
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: add
|
||||
|
||||
[Product Block Editor]: implement `Choose products for me` button
|
|
@ -9,6 +9,13 @@ import {
|
|||
} from '@wordpress/element';
|
||||
import { useWooBlockProps } from '@woocommerce/block-templates';
|
||||
import { Product } from '@woocommerce/data';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { reusableBlock } from '@wordpress/icons';
|
||||
// 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 { useEntityId } from '@wordpress/core-data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -31,6 +38,7 @@ import {
|
|||
LinkedProductListBlockAttributes,
|
||||
LinkedProductListBlockEmptyState,
|
||||
} from './types';
|
||||
import getRelatedProducts from '../../../utils/get-related-products';
|
||||
|
||||
export function EmptyStateImage( {
|
||||
image,
|
||||
|
@ -56,7 +64,7 @@ export function EmptyStateImage( {
|
|||
}
|
||||
}
|
||||
|
||||
export function Edit( {
|
||||
export function LinkedProductListBlockEdit( {
|
||||
attributes,
|
||||
context: { postType },
|
||||
}: ProductEditorBlockEditProps< LinkedProductListBlockAttributes > ) {
|
||||
|
@ -66,6 +74,9 @@ export function Edit( {
|
|||
linkedProducts: [],
|
||||
searchedProducts: [],
|
||||
} );
|
||||
|
||||
const productId = useEntityId( 'postType', postType );
|
||||
|
||||
const loadLinkedProductsDispatcher =
|
||||
getLoadLinkedProductsDispatcher( dispatch );
|
||||
const searchProductsDispatcher = getSearchProductsDispatcher( dispatch );
|
||||
|
@ -100,6 +111,7 @@ export function Edit( {
|
|||
product,
|
||||
state.linkedProducts
|
||||
);
|
||||
|
||||
setLinkedProductIds( newLinkedProductIds );
|
||||
}
|
||||
|
||||
|
@ -112,8 +124,49 @@ export function Edit( {
|
|||
setLinkedProductIds( newLinkedProductIds );
|
||||
}
|
||||
|
||||
async function chooseProductsForMe() {
|
||||
dispatch( {
|
||||
type: 'LOADING_LINKED_PRODUCTS',
|
||||
payload: {
|
||||
isLoading: true,
|
||||
},
|
||||
} );
|
||||
|
||||
const relatedProducts = ( await getRelatedProducts(
|
||||
productId
|
||||
) ) as Product[];
|
||||
|
||||
dispatch( {
|
||||
type: 'LOADING_LINKED_PRODUCTS',
|
||||
payload: {
|
||||
isLoading: false,
|
||||
},
|
||||
} );
|
||||
|
||||
if ( ! relatedProducts ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newLinkedProducts = selectSearchedProductDispatcher(
|
||||
relatedProducts,
|
||||
[]
|
||||
);
|
||||
|
||||
setLinkedProductIds( newLinkedProducts );
|
||||
}
|
||||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<div className="wp-block-woocommerce-product-linked-list-field__form-group-header">
|
||||
<Button
|
||||
variant="tertiary"
|
||||
icon={ reusableBlock }
|
||||
onClick={ chooseProductsForMe }
|
||||
>
|
||||
{ __( 'Choose products for me', 'woocommerce' ) }
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="wp-block-woocommerce-product-linked-list-field__form-group-content">
|
||||
<ProductSelect
|
||||
items={ state.searchedProducts }
|
||||
|
|
|
@ -3,6 +3,12 @@
|
|||
flex-direction: column;
|
||||
gap: $grid-unit-30;
|
||||
|
||||
&__form-group-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
.woocommerce-advice-card {
|
||||
min-height: 233px; // min height to cover the min rows rendered in the table on its back
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Internal dependencies
|
||||
*/
|
||||
import blockConfiguration from './block.json';
|
||||
import { Edit } from './edit';
|
||||
import { LinkedProductListBlockEdit } from './edit';
|
||||
import { registerProductEditorBlockType } from '../../../utils';
|
||||
|
||||
const { name, ...metadata } = blockConfiguration;
|
||||
|
@ -11,7 +11,7 @@ export { metadata, name };
|
|||
|
||||
export const settings = {
|
||||
example: {},
|
||||
edit: Edit,
|
||||
edit: LinkedProductListBlockEdit,
|
||||
};
|
||||
|
||||
export function init() {
|
||||
|
|
|
@ -8,7 +8,7 @@ export type State = {
|
|||
linkedProducts: Product[];
|
||||
searchedProducts: Product[];
|
||||
isLoading?: boolean;
|
||||
selectedProduct?: Product;
|
||||
selectedProduct?: Product | Product[];
|
||||
};
|
||||
|
||||
export type ActionType =
|
||||
|
@ -120,10 +120,14 @@ export function getSelectSearchedProductDispatcher(
|
|||
dispatch: ( value: Action ) => void
|
||||
) {
|
||||
return function selectSearchedProductDispatcher(
|
||||
selectedProduct: Product,
|
||||
selectedProduct: Product | Product[],
|
||||
linkedProducts: Product[]
|
||||
) {
|
||||
const newLinkedProducts = [ ...linkedProducts, selectedProduct ];
|
||||
if ( ! Array.isArray( selectedProduct ) ) {
|
||||
selectedProduct = [ selectedProduct ];
|
||||
}
|
||||
|
||||
const newLinkedProducts = [ ...linkedProducts, ...selectedProduct ];
|
||||
|
||||
dispatch( {
|
||||
type: 'SELECT_SEARCHED_PRODUCT',
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { select, resolveSelect } from '@wordpress/data';
|
||||
import type { Product } from '@woocommerce/data';
|
||||
|
||||
export default async function getRelatedProducts( productId: number ) {
|
||||
const { getEntityRecord } = select( 'core' );
|
||||
const product = getEntityRecord( 'postType', 'product', productId );
|
||||
if ( ! product ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const relatedProductIds = product?.related_ids;
|
||||
if ( ! relatedProductIds ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { getEntityRecords } = resolveSelect( 'core' );
|
||||
return ( await getEntityRecords( 'postType', 'product', {
|
||||
include: relatedProductIds,
|
||||
} ) ) as Product[];
|
||||
}
|
Loading…
Reference in New Issue