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

Add withCategories and withAttributes HOCs #935

Merged
merged 12 commits into from
Sep 4, 2019

Conversation

Aljullu
Copy link
Contributor

@Aljullu Aljullu commented Sep 2, 2019

This PR:

  • Creates withCategories and withAttributes HOC.
  • Makes it so Product Category Control and Product Attribute Control display API errors to the user.
  • Refactors error handling in all HOCs so JS errors can be handled too.

Screenshots

image

How to test the changes in this Pull Request:

  1. Create a post with a Products by Category and Products by Attribute blocks.
  2. In src/RestApi/Controllers/ProductCategories.php modify this line with:
-if ( ! $taxonomy || ! \taxonomy_exists( $taxonomy ) ) {
+if( true ) {
  1. In src/RestApi/Controllers/ProductAttributes.php modify this one with:
-if ( ! current_user_can( 'edit_posts' ) ) {
+if ( true ) {
  1. Reload the post and verify errors are displayed.

@Aljullu Aljullu added status: in progress type: refactor The issue/PR is related to refactoring. labels Sep 2, 2019
@Aljullu Aljullu added this to the 2.5 milestone Sep 2, 2019
@Aljullu Aljullu self-assigned this Sep 2, 2019
@Aljullu Aljullu requested review from ehg and a team and removed request for ehg September 2, 2019 11:46
assets/js/base/utils/errors.js Outdated Show resolved Hide resolved
assets/js/base/utils/errors.js Show resolved Hide resolved
// let <ApiErrorPlaceholder /> handle the message to display.
apiMessage: null,
};
const formatErrorMessage = ( error, messageProperty = 'frontendMessage' ) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it'd be useful to have a doc block here, especially for describing what messageProperty is a reference to and acceptable values.

Also I'd be wary of getting to context specific with frontendMessage string here. What about userFriendly instead (I'm guessing the idea here is a non-dev type error message?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

frontendMessage was referring to errors produced by the frontend, but not necessarily user-friendly. For example, a JS error.

I completely refactored that part of the code in 2ac40b0, let me know how it looks now.

Copy link
Contributor

@nerrad nerrad Sep 4, 2019

Choose a reason for hiding this comment

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

frontendMessage was referring to errors produced by the frontend, but not necessarily user-friendly. For example, a JS error

That's a good argument for not using frontend though as it's still ambiguous. In continuing with the intended purpose, I would expect it to be something like general (for general JS error) as opposed to api (for error in an api response).

I have some more feedback on the refactor in my review comments to be published soon (including a suggestion to continue iterating on it in a separate pull so we don't block this one).

@@ -5,11 +5,21 @@ import { __ } from '@wordpress/i18n';
import PropTypes from 'prop-types';
import { escapeHTML } from '@wordpress/escape-html';

const getErrorMessage = ( { apiMessage, message } ) => {
const getErrorMessage = ( { apiMessage, message, frontendMessage } ) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar comment here as I left elsewhere. I think frontendMessage is too specific a variable name. I anticipate this may be a type of message left in non frontend contexts as well. Would userFriendlyMessage or informalMessage be a better fit here?

assets/js/components/product-attribute-control/index.js Outdated Show resolved Hide resolved
assets/js/components/product-category-control/index.js Outdated Show resolved Hide resolved
return apiFetch( {
path: addQueryArgs( `${ ENDPOINTS.products }/categories`, { per_page: -1 } ),
} );
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Not needed in this pull, but with the number of blocks calling product categories, this seems like a good thing to move to a wp.data store so that blocks using categories can share what is retrieved. This will help with limiting the number of queries to the server (same for product attributes and product attribute terms). That's something I can do in a pull?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, sounds like a good idea! 🙂

assets/js/hocs/test/with-attributes.js Outdated Show resolved Hide resolved
@Aljullu
Copy link
Contributor Author

Aljullu commented Sep 4, 2019

Thanks for the review @nerrad. This is ready for another look.

@Aljullu Aljullu requested a review from nerrad September 4, 2019 10:34
assets/js/base/utils/errors.js Outdated Show resolved Hide resolved
return {
message: error.message,
type: error.type || 'frontend',
};
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the direction with providing a "type" to the error. However:

  • defaults vary in the logic. Why?
  • any caught exception always defaults to frontend as the type. Why?

I'm not sure we've landed on a good api for error handling yet, but it probably should be iterated on in it's own pull.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The rationale behind that was that an API error will be a Response object, so it will have a json method, while errors produced in the frontend will not have that method.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, there's a bit of code smell here with the confusing logic. Let's iterate on this in a follow-up (not urgent).

assets/js/base/utils/errors.js Outdated Show resolved Hide resolved
// let <ApiErrorPlaceholder /> handle the message to display.
apiMessage: null,
};
const formatErrorMessage = ( error, messageProperty = 'frontendMessage' ) => {
Copy link
Contributor

@nerrad nerrad Sep 4, 2019

Choose a reason for hiding this comment

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

frontendMessage was referring to errors produced by the frontend, but not necessarily user-friendly. For example, a JS error

That's a good argument for not using frontend though as it's still ambiguous. In continuing with the intended purpose, I would expect it to be something like general (for general JS error) as opposed to api (for error in an api response).

I have some more feedback on the refactor in my review comments to be published soon (including a suggestion to continue iterating on it in a separate pull so we don't block this one).

}

onExpandAttribute( item ) {
const ProductAttributeControl = ( { attributes, error, expandedAttribute, onChange, onOperatorChange, isLoading, operator, selected, termsAreLoading, termsList } ) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a long line and should be split into multiline arguments here. #

Also applies to other refactors to functional components.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How does it sound installing prettier and setting it as a pre-commit hook in a follow-up and dealing with these issues there? That's what we were using in WooCommerce Admin and seems like the kind of job better suited for a machine than for a human. 😄


onExpandAttribute( item ) {
const ProductAttributeControl = ( { attributes, error, expandedAttribute, onChange, onOperatorChange, isLoading, operator, selected, termsAreLoading, termsList } ) => {
const onExpandAttribute = ( item ) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be declared outside of the component otherwise the <SearchListItem /> will receive a new function on every re-render of this component. One of the gotchas of switching to functional components from a class component. It's okay when you're not passing the function through as a prop but it's being passed through as the value for the onSelect prop here.

Of course, this may be a moot point because there are other places where there will always be a new reference passed through as a prop (see here) for example. So if we're fine with <SearchListItem /> always re-rendering when <ProductAttributeControl /> does, then we can just leave things as is I suppose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

onExpandAttribute relies on the onChange prop, so we would need to re-create the function anyway on every re-render with the new onChange, no?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh right! yup.

Copy link
Contributor

@nerrad nerrad left a comment

Choose a reason for hiding this comment

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

I'm happy with where this pull is at for now. Let's iterate on other feedback in their own pulls and 🚢 this.

return {
message: error.message,
type: error.type || 'frontend',
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Right, there's a bit of code smell here with the confusing logic. Let's iterate on this in a follow-up (not urgent).

@Aljullu Aljullu merged commit e01c341 into master Sep 4, 2019
@Aljullu Aljullu deleted the update/errors-categories-attributes branch September 4, 2019 16:07
@Aljullu Aljullu added the skip-changelog PRs that you don't want to appear in the changelog. label Sep 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
skip-changelog PRs that you don't want to appear in the changelog. type: refactor The issue/PR is related to refactoring.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants