Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Make Product Collection product-centric #9469

Closed
wants to merge 24 commits into from

Conversation

kmanijak
Copy link
Contributor

@kmanijak kmanijak commented May 15, 2023

This PR changes the way Product Collection / Product Template fetches the data compared to Products block (with inner Post Template).

Product Template:

  • doesn't fetch post data as it's unnecessary
  • fetches products and their details which then are passed to the inner blocks, so they don't have to do a request for product details

Remaining issue:

  • there's still one unnecessary request made for products (with incorrect query details). This is due to the way with-product-data-context HOC is organized. There's a hook to fetch the product data and even though the product is provided and data from the hook will be ignored (check if statement here), it's still making a request. By default, it would make a request per each product separately, however thanks to the different data structure, the id here, is not defined, hence there's just a single call made. This requires rethinking/refactoring, however, we need to keep in mind All Products and Products block (and potentially others) in which Product Elements are in use. Having said that, I decided to accept this downside for now.

Note: changes in src/BlockTypes/AddToCartForm.php are not related to this PR - it's just lining improvement.

Fixes woocommerce/woocommerce#42388

Accessibility

Screenshots

Comparison of requests in Editor (Filters applied: fetch requests, including "product" in path):

Products block Product Collection
image image

Testing

Automated Tests

  • Changes in this PR are covered by Automated Tests.
    • Unit tests
    • E2E tests

User Facing Testing

  1. Go to Editor and edit Product Catalog
  2. Add Products and Product Collection blocks side by side
  3. Make sure both blocks load properly and display the same set of products by default
  4. Save and go to frontend
  5. Make sure both blocks load properly and display the same set of products by default
  6. Change the pages in both blocks and make sure pagination works correctly
  • Do not include in the Testing Notes

WooCommerce Visibility

  • WooCommerce Core
  • Feature plugin
  • Experimental

Performance Impact

This PR speeds up the loading time of Product Collection in the Editor. You can see the number of requests is decreased drastically:

  • in Products there are at least 2 requests per product displayed and additional unnecessary call for all posts
  • in Product Collection there are two requests made in total. One of them is redundant and should be optimized in future

@github-actions
Copy link
Contributor

github-actions bot commented May 15, 2023

The release ZIP for this PR is accessible via:

https://wcblocks.wpcomstaging.com/wp-content/uploads/woocommerce-gutenberg-products-block-9469.zip

Script Dependencies Report

The compare-assets action has detected some changed script dependencies between this branch and trunk. Please review and confirm the following are correct before merging.

Script Handle Added Removed
product-template.js wp-api-fetch ⚠️

This comment was automatically generated by the ./github/compare-assets action.

TypeScript Errors Report

  • Files with errors: 468
  • Total errors: 2224

⚠️ ⚠️ This PR introduces new TS errors on 5 files:

assets/js/blocks/product-collection/inspector-controls/index.tsx

assets/js/blocks/product-collection/inspector-controls/keyword-control.tsx

assets/js/blocks/product-template/edit.tsx

assets/js/blocks/product-template/products-middleware.tsx

assets/js/blocks/product-template/test/products-middleware.ts

comments-aggregator

@github-actions
Copy link
Contributor

github-actions bot commented May 15, 2023

Size Change: +945 B (0%)

Total Size: 1.17 MB

Filename Size Change
build/all-products.js 40.3 kB +20 B (0%)
build/mini-cart-contents.js 18.1 kB -1 B (0%)
build/product-categories.js 2.71 kB +1 B (0%)
build/product-template.js 4.27 kB +925 B (+28%) 🚨
ℹ️ View Unchanged
Filename Size
build/active-filters-frontend.js 8.63 kB
build/active-filters-wrapper-frontend.js 7.58 kB
build/active-filters.js 7.48 kB
build/all-products-frontend.js 12.2 kB
build/all-reviews.js 7.86 kB
build/attribute-filter-frontend.js 23 kB
build/attribute-filter-wrapper-frontend.js 7.73 kB
build/attribute-filter.js 13.3 kB
build/blocks-checkout.js 35.1 kB
build/breadcrumbs.js 2.13 kB
build/cart-blocks/cart-accepted-payment-methods-frontend.js 1.38 kB
build/cart-blocks/cart-cross-sells-frontend.js 253 B
build/cart-blocks/cart-cross-sells-products--product-price-frontend.js 2.92 kB
build/cart-blocks/cart-cross-sells-products-frontend.js 3.77 kB
build/cart-blocks/cart-express-payment--checkout-blocks/express-payment-frontend.js 5.17 kB
build/cart-blocks/cart-express-payment-frontend.js 719 B
build/cart-blocks/cart-items-frontend.js 302 B
build/cart-blocks/cart-line-items--mini-cart-contents-block/products-table-frontend.js 5.57 kB
build/cart-blocks/cart-line-items-frontend.js 1.06 kB
build/cart-blocks/cart-order-summary-frontend.js 1.27 kB
build/cart-blocks/cart-totals-frontend.js 308 B
build/cart-blocks/empty-cart-frontend.js 345 B
build/cart-blocks/filled-cart-frontend.js 655 B
build/cart-blocks/order-summary-coupon-form-frontend.js 1.63 kB
build/cart-blocks/order-summary-discount-frontend.js 2.12 kB
build/cart-blocks/order-summary-fee-frontend.js 274 B
build/cart-blocks/order-summary-heading-frontend.js 333 B
build/cart-blocks/order-summary-shipping-frontend.js 17.1 kB
build/cart-blocks/order-summary-subtotal-frontend.js 274 B
build/cart-blocks/order-summary-taxes-frontend.js 436 B
build/cart-blocks/proceed-to-checkout-frontend.js 1.44 kB
build/cart-frontend.js 30 kB
build/cart.js 45.2 kB
build/catalog-sorting.js 1.7 kB
build/checkout-blocks/actions-frontend.js 1.88 kB
build/checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 4.69 kB
build/checkout-blocks/billing-address-frontend.js 1.18 kB
build/checkout-blocks/contact-information-frontend.js 2.04 kB
build/checkout-blocks/express-payment-frontend.js 1.14 kB
build/checkout-blocks/fields-frontend.js 331 B
build/checkout-blocks/order-note-frontend.js 1.14 kB
build/checkout-blocks/order-summary-cart-items-frontend.js 3.76 kB
build/checkout-blocks/order-summary-coupon-form-frontend.js 1.79 kB
build/checkout-blocks/order-summary-discount-frontend.js 2.29 kB
build/checkout-blocks/order-summary-fee-frontend.js 276 B
build/checkout-blocks/order-summary-frontend.js 1.28 kB
build/checkout-blocks/order-summary-shipping-frontend.js 17 kB
build/checkout-blocks/order-summary-subtotal-frontend.js 274 B
build/checkout-blocks/order-summary-taxes-frontend.js 436 B
build/checkout-blocks/payment-frontend.js 8.29 kB
build/checkout-blocks/pickup-options-frontend.js 4.84 kB
build/checkout-blocks/shipping-address-frontend.js 1.18 kB
build/checkout-blocks/shipping-method-frontend.js 2.64 kB
build/checkout-blocks/shipping-methods-frontend.js 6.41 kB
build/checkout-blocks/terms-frontend.js 1.56 kB
build/checkout-blocks/totals-frontend.js 360 B
build/checkout-frontend.js 31.9 kB
build/checkout.js 46.6 kB
build/customer-account.js 3.18 kB
build/featured-category.js 15.1 kB
build/featured-product.js 15.3 kB
build/filter-wrapper-frontend.js 14.3 kB
build/filter-wrapper.js 2.4 kB
build/general-style-rtl.css 1.31 kB
build/general-style.css 1.31 kB
build/handpicked-products.js 8.05 kB
build/legacy-template.js 6.8 kB
build/mini-cart-component-frontend.js 30.7 kB
build/mini-cart-contents-block/cart-button-frontend.js 1.73 kB
build/mini-cart-contents-block/checkout-button-frontend.js 1.81 kB
build/mini-cart-contents-block/empty-cart-frontend.js 360 B
build/mini-cart-contents-block/filled-cart-frontend.js 267 B
build/mini-cart-contents-block/footer-frontend.js 3.83 kB
build/mini-cart-contents-block/items-frontend.js 237 B
build/mini-cart-contents-block/products-table-frontend.js 588 B
build/mini-cart-contents-block/shopping-button-frontend.js 530 B
build/mini-cart-contents-block/title-frontend.js 1.9 kB
build/mini-cart-contents-block/title-items-counter-frontend.js 1.59 kB
build/mini-cart-contents-block/title-label-frontend.js 1.53 kB
build/mini-cart-frontend.js 2.85 kB
build/mini-cart.js 5.92 kB
build/price-filter-frontend.js 14.6 kB
build/price-filter-wrapper-frontend.js 6.77 kB
build/price-filter.js 8.56 kB
build/price-format.js 1.19 kB
build/product-add-to-cart--product-button--product-image--product-price--product-rating--product-sale-bad--49d3ecb2.js 250 B
build/product-add-to-cart--product-button--product-image--product-rating--product-title.js 151 B
build/product-add-to-cart-frontend.js 6.52 kB
build/product-add-to-cart.js 8.84 kB
build/product-best-sellers.js 8.36 kB
build/product-button--product-image--product-price--product-rating--product-sale-badge--product-sku--prod--5bce0384.js 955 B
build/product-button-frontend.js 2.65 kB
build/product-button.js 3.97 kB
build/product-category.js 9.37 kB
build/product-collection.js 12.3 kB
build/product-image-frontend.js 2.61 kB
build/product-image.js 4.14 kB
build/product-new.js 8.65 kB
build/product-on-sale.js 8.65 kB
build/product-price-frontend.js 204 B
build/product-price.js 1.68 kB
build/product-query.js 11.9 kB
build/product-rating-frontend.js 2.33 kB
build/product-rating.js 1.03 kB
build/product-results-count.js 1.66 kB
build/product-sale-badge-frontend.js 1.79 kB
build/product-sale-badge.js 666 B
build/product-search.js 2.63 kB
build/product-sku-frontend.js 1.83 kB
build/product-sku.js 535 B
build/product-stock-indicator-frontend.js 2.03 kB
build/product-stock-indicator.js 731 B
build/product-summary-frontend.js 2.25 kB
build/product-summary.js 1 kB
build/product-tag.js 9.01 kB
build/product-title-frontend.js 2.21 kB
build/product-title.js 3.66 kB
build/product-top-rated.js 8.91 kB
build/products-by-attribute.js 9.75 kB
build/rating-filter-frontend.js 21.4 kB
build/rating-filter-wrapper-frontend.js 6.23 kB
build/rating-filter.js 6.93 kB
build/reviews-by-category.js 12.1 kB
build/reviews-by-product.js 13.3 kB
build/reviews-frontend.js 7.17 kB
build/single-product.js 11.1 kB
build/stock-filter-frontend.js 21.7 kB
build/stock-filter-wrapper-frontend.js 6.48 kB
build/stock-filter.js 7.66 kB
build/store-notices.js 1.68 kB
build/vendors--attribute-filter-wrapper--cart-blocks/order-summary-coupon-form--cart-blocks/order-summary--48e1e4bb-frontend.js 6.84 kB
build/vendors--attribute-filter-wrapper--cart-blocks/order-summary-shipping--checkout-blocks/billing-addr--d9f38f9d-frontend.js 4.19 kB
build/vendors--attribute-filter-wrapper-frontend.js 5.11 kB
build/vendors--cart-blocks/cart-cross-sells-products--cart-blocks/cart-line-items--cart-blocks/cart-order--3c5fe802-frontend.js 5.26 kB
build/vendors--cart-blocks/cart-line-items--checkout-blocks/order-summary-cart-items--mini-cart-contents---233ab542-frontend.js 3.57 kB
build/vendors--cart-blocks/order-summary-shipping--checkout-blocks/billing-address--checkout-blocks/order--decc3dc6-frontend.js 19.4 kB
build/vendors--checkout-blocks/pickup-options--checkout-blocks/shipping-methods-frontend.js 8.25 kB
build/vendors--checkout-blocks/shipping-method-frontend.js 12.4 kB
build/vendors--price-filter-wrapper-frontend.js 2.2 kB
build/vendors--product-add-to-cart-frontend.js 7.25 kB
build/vendors--rating-filter-wrapper-frontend.js 5.11 kB
build/vendors--stock-filter-wrapper-frontend.js 5.11 kB
build/wc-blocks-data.js 22.3 kB
build/wc-blocks-editor-style-rtl.css 6.21 kB
build/wc-blocks-editor-style.css 6.21 kB
build/wc-blocks-google-analytics.js 1.56 kB
build/wc-blocks-middleware.js 934 B
build/wc-blocks-registry.js 3.15 kB
build/wc-blocks-shared-context.js 1.1 kB
build/wc-blocks-shared-hocs.js 1.75 kB
build/wc-blocks-style-rtl.css 28 kB
build/wc-blocks-style.css 28 kB
build/wc-blocks-vendors-style-rtl.css 1.96 kB
build/wc-blocks-vendors-style.css 1.96 kB
build/wc-blocks-vendors.js 65.1 kB
build/wc-blocks.js 3.7 kB
build/wc-payment-method-bacs.js 816 B
build/wc-payment-method-cheque.js 811 B
build/wc-payment-method-cod.js 909 B
build/wc-payment-method-paypal.js 837 B
build/wc-settings.js 2.6 kB
build/wc-shipping-method-pickup-location.js 30.4 kB
build/woo-directives-runtime.js 2.73 kB
build/woo-directives-vendors.js 7.91 kB

compressed-size-action

@kmanijak kmanijak added skip-changelog PRs that you don't want to appear in the changelog. block: product collection Issues related to the Product Collection block labels May 16, 2023
@kmanijak kmanijak marked this pull request as ready for review May 16, 2023 10:36
@kmanijak kmanijak requested a review from imanish003 May 16, 2023 10:36
@imanish003
Copy link
Contributor

Hi @kmanijak, great work! 🙌🏻

I noticed that on the editor side, the titles of the products are not showing correctly. In the screenshot below, you can see that all the titles are displayed as "Post Title" in the Product Collection block. Are you able to reproduce this issue?

image

templateCategory,
} );

const { products, productsLoading } = useStoreProducts( finalQuery );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, is there any reason we want to move away from getEntityRecords? Because recently, I came across P2 pdToLP-Aj-p2 in which Darren mentioned that we should "Converge on using the entity data store for product data in the editor" 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to improve the efficiency of fetching the product data. By default getEntityRecords fetches the data about the post. To make it fetch the product data (like prices, images, etc.) it would require to use a middleware (probably writing one to redirect the fetch, which is not ideal). I made a short POC some time ago, available here: #9162.

Because of that, I think it makes sense to use useStoreProducts for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer us to implement the entity records store (with middleware) please. This will help us move towards the convergence of product block usage across multiple views (product editor, site editor, etc). It's a good opportunity to make this change.

I started experimenting with something that could replace the withProductDataContext HOC in the price block refinement PR that might be useful to extract out to its own file. While the new ProviderFromAPI component still implements useStoreProducts, I've already noted it as a place to derive the data from the entity data store (and it'd be a good place to optionally implement a data transformation layer perhaps).

That work is still in progress but sharing it in case its useful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer us to implement the entity records store (with middleware) please. This will help us move towards the convergence of product block usage across multiple views (product editor, site editor, etc). It's a good opportunity to make this change.

Thanks for your input! In that case, let me start moving toward the entity records store. I was a bit skeptical after the previous attempt, but I was redirecting the request to the Store API, while maybe we could get the data from WooCommerce API (like in this example middleware) - is that what you have in mind or do you think to still keep using Store API underneath?

I started experimenting with something that could replace the withProductDataContext HOC in the price block refinement PR that might be useful to extract out to its own file. While the new ProviderFromAPI component still implements useStoreProducts, I've already noted it as a place to derive the data from the entity data store (and it'd be a good place to optionally implement a data transformation layer perhaps).

I'll definitely take a deeper look. I think that solution like that should be prepared to avoid data fetch in case the product is already provided downstream (like it's intended to be in case of Product Collection). What I mean is in the case of All Products and Products block, inner blocks are responsible to fetch the product data which is then shared through the context (withProductDataContext ) to avoid fetching duplication. While in Product Collection the idea was to fetch all of the product data at once and just pass it downstream.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I was redirecting the request to the Store API, while maybe we could get the data from WooCommerce API (like in this example middleware) - is that what you have in mind or do you think to still keep using Store API underneath?

Yup, that's what I was thinking of (use WooCommerce API). Since it's in the admin, it aligns better with permissions on the authed endpoint (and lays the future groundwork for potentially editing content in place). Of course, you'll have to be careful for any client code that might be loaded on the frontend (i.e. the All Products block - which would still need to use the unauthed Store API).

While in Product Collection the idea was to fetch all of the product data at once and just pass it downstream.

Yup, that's what I was thinking of for the implementation I linked to. If it worked well, I planned on putting it into a separate PR so that the provider is at a higher level in the block tree (i.e. the Products Collection block).

@kmanijak kmanijak force-pushed the add/product-centric-product-collection branch from 981f677 to 39c06e3 Compare May 18, 2023 13:16
@kmanijak
Copy link
Contributor Author

I noticed that on the editor side, the titles of the products are not showing correctly. In the screenshot below, you can see that all the titles are displayed as "Post Title" in the Product Collection block. Are you able to reproduce this issue?

In order to fix that:

  1. I tried the option to use Product Title from product elements, however, achieving the correct result requires making the Product Title available in Product Collection (and probably Products) in the same way as Product Summary was prepared some time ago (Add product query support for Product Summary block #7774). However, that work was reverted soon after (Revert "Add product query support for Product Summary block" #7818) due to the decision to keep the blocks as variations whenever possible.
    Currently, when using the Product Title from Product Elements it works fine in the editor, but it doesn't render on the frontend (as expected - like I said it requires work similar to that described above).
    That brings us to the discussion of whether we should stick to the variations whenever possible. Considering we're building Product Collection (to avoid using variation API), maybe we should stick to our own Product Title, instead of using a core variation.
    More context: p1669901167042349-slack-C02FL3X7KR6

  2. I eventually reverted back to the core/post-title variation, but to make it work, it's required to pass postId as a context, which in this case has a terrible effect on performance:

  • core/post-title does its unnecessary in our context requests (more context: per0F9-tT-p2)
  • it triggers a requests for product data which we already have. Requests are triggered by this hook, which due to being hook cannot be skipped without refactoring.

Summary:

  • in current shape, product title is displaying correctly, but loading is terribly slow, so this PR cannot be merged like that
  • due to the above I'm converting this PR to draft
  • I think we should consider using our in-house Product Title instead of core/post-title variation for our own benefit (optimization, bigger control).

cc: @imanish003 - I'm leaving the PR in this shape, feel free to pick it up or wait with it until I'm back 🙏
cc: @tjcafferkey, @danielwrobert - regarding the conversation about using Product Title instead of Post Title variation

@kmanijak kmanijak marked this pull request as draft May 18, 2023 13:48
@github-actions
Copy link
Contributor

This PR has been marked as stale because it has not seen any activity within the past 7 days. Our team uses this tool to help surface pull requests that have slipped through review.

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.

@github-actions github-actions bot added the status: stale Stale issues and PRs have had no updates for 60 days. label May 26, 2023
@imanish003 imanish003 removed the status: stale Stale issues and PRs have had no updates for 60 days. label May 26, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Jun 3, 2023

This PR has been marked as stale because it has not seen any activity within the past 7 days. Our team uses this tool to help surface pull requests that have slipped through review.

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.

@github-actions github-actions bot added the status: stale Stale issues and PRs have had no updates for 60 days. label Jun 3, 2023
@kmanijak kmanijak changed the title Add/product centric product collection Make Product Collection product-centric Jun 5, 2023
@imanish003 imanish003 removed the status: stale Stale issues and PRs have had no updates for 60 days. label Jun 5, 2023
@github-actions
Copy link
Contributor

price is already formatted, not in a lowest currency unit...

price is already formatted, not in a lowest currency unit as in store API


// @todo: price is already formatted, not in a lowest currency unit as in store API
const { price, regular_price, sale_price } = input;
return {
price,
regular_price,
sale_price,
price_range: null,
...currency,
};
};
const createAddToCartProperty = ( input: WooCommerceAPIproductResponse ) => {
const { id, name } = input;

🚀 This comment was generated by the automations bot based on a todo comment in 2eabf7b in #9469. cc @kmanijak

@github-actions
Copy link
Contributor

get actual currency data

get actual currency data


// @todo: get actual currency data
const currency = {
currency_code: 'PLN',
currency_symbol: 'z\u0142',
currency_minor_unit: 2,
currency_decimal_separator: ',',
currency_thousand_separator: '',
currency_prefix: '',
currency_suffix: ' z\u0142',
};
// @todo: price is already formatted, not in a lowest currency unit as in store API
const { price, regular_price, sale_price } = input;

🚀 This comment was generated by the automations bot based on a todo comment in 2eabf7b in #9469. cc @kmanijak

@github-actions
Copy link
Contributor

Add category link

Add category link


// @todo: Add category link
return category;
};
return categories.map( adjustCategory );
};
const createDescriptionProperty = ( input: ProductItem ) => {
const { description } = input;
return `<p>${ description }</p>`;
};
const createShortDescriptionProperty = ( input: ProductItem ) => {
const { short_description } = input;
return `<p>${ short_description }</p>`;

🚀 This comment was generated by the automations bot based on a todo comment in c0ffc31 in #9469. cc @kmanijak

@kmanijak
Copy link
Contributor Author

Closing this as it's stall. The topic will have to be revisited but not ATM.

@kmanijak kmanijak closed this Nov 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
block: product collection Issues related to the Product Collection block skip-changelog PRs that you don't want to appear in the changelog. team: Kirigami & Origami
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make Product Collection product-centric
3 participants