-
Notifications
You must be signed in to change notification settings - Fork 219
Conversation
Implemented as another variation of the Product Query block.
The release ZIP for this PR is accessible via:
|
Script Dependencies ReportThe
This comment was automatically generated by the |
TypeScript Errors ReportFiles with errors: 432
assets/js/blocks/product-query/variations/handpicked-products.tsx
|
Size Change: +295 B (0%) Total Size: 1.11 MB
ℹ️ View Unchanged
|
This PR has been marked as If deemed still relevant, the pr can be kept active by ensuring it's up to date with the main branch and removing the stale label. |
The release ZIP for this PR is accessible via:
Script Dependencies ReportThe
This comment was automatically generated by the TypeScript Errors Report
assets/js/blocks/product-query/inspector-controls/product-selector.tsx
|
Previously, we thought of the hand-picked products block as a variation. Now we are allowing to hand-pick products on any “Products” block.
PR bumped to the next milestone (10.3.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @sunyatasattva,
I've tested the changes, and everything is working as expected. Excellent work, as always 🙌🏻
I've left a few minor comments, but they shouldn't block the PR, so I'm pre-approving it. 🚀
import { ProductQueryBlock } from '../types'; | ||
import { setQueryAttribute } from '../utils'; | ||
|
||
export const ProductSelector = ( props: ProductQueryBlock ) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am nitpicking here, but how do you feel about restructuring the attributes property from the props object to simplify property access:
export const ProductSelector = ( props: ProductQueryBlock ) => { | |
export const ProductSelector = ({ attributes }: ProductQueryBlock) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion! Normally, I'd be up for it, but in this case you can see that we use props
as a whole twice on L76 and L85.
const [ productsList, setProductsList ] = useState< ProductResponseItem[] >( | ||
[] | ||
); | ||
|
||
useEffect( () => { | ||
getProducts( { selected: [] } ).then( ( results ) => { | ||
setProductsList( results as ProductResponseItem[] ); | ||
} ); | ||
}, [] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's needed here but just wanted to share my thoughts. Maybe we can create a custom hook to fetch and manage the productsList state to separate concerns and make the component more modular:
const useProductsList = (): ProductResponseItem[] => {
const [productsList, setProductsList] = useState<ProductResponseItem[]>([]);
useEffect(() => {
getProducts({ selected: [] }).then((results) => {
setProductsList(results as ProductResponseItem[]);
});
}, []);
return productsList;
};
And use it in the component like this:
const productsList = useProductsList();
onChange={ ( values ) => { | ||
const ids = values | ||
.map( | ||
( nameOrId ) => | ||
productsList.find( | ||
( product ) => | ||
product.name === nameOrId || | ||
product.id === Number( nameOrId ) | ||
)?.id | ||
) | ||
.filter( Boolean ) | ||
.map( String ); | ||
|
||
if ( ! ids.length && props.attributes.query.include ) { | ||
const prunedQuery = objectOmit( | ||
props.attributes.query, | ||
'include' | ||
); | ||
|
||
setQueryAttribute( | ||
{ | ||
...props, | ||
attributes: { | ||
...props.attributes, | ||
query: prunedQuery, | ||
}, | ||
}, | ||
{} | ||
); | ||
} else { | ||
setQueryAttribute( props, { | ||
include: ids, | ||
} ); | ||
} | ||
} } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can extract the logic of the onChange callback into a separate function to make the component more readable and maintainable?
const handleTokensChange = (values: string[]) => {
...
};
...
<FormTokenField
...
onChange={handleTokensChange}
...
/>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea good call.
/** | ||
* Returns an object without a key. | ||
*/ | ||
function objectOmit< T, K extends keyof T >( obj: T, key: K ) { | ||
const { [ key ]: omit, ...rest } = obj; | ||
|
||
return rest; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! Thanks for moving this to utils 🙌🏻
* Refactor `useProductsList` into own hook. * Refactor `onTokenChange` outside of the component.
Implements the ProductSelector advanced filter within the “Products (Beta)” block. The filter allows the merchant to narrow down the exact products to which all subsequent filters will be applied, mirroring the functionality of the existing “Hand-picked Products” plus all the other functionalities available from the “Products (Beta)” block.
This PR implements the
ProductSelector
advanced filter within the “Products (Beta)” block. The filter allows the merchant to narrow down the exact products to which all subsequent filters will be applied, mirroring the functionality of the existing “Hand-picked Products” plus all the other functionalities available from the “Products (Beta)” block.Fixes #7633
Accessibility
prefers-reduced-motion
Other Checks
Screenshots
handpicked-products-screen-recording.mov
The video above shows a different block called “Hand-picked Products”. The current PR doesn't include this variation and includes the Product Selector within the normal block.
Testing
Automated Tests
User Facing Testing
Simplest path
Complex path
WooCommerce Visibility
Performance Impact
Changelog