Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: map errors into an object #1108

Conversation

ivopereira15
Copy link

PR Type

[ X] Bugfix
[ X] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no API changes)
[ ] Build-related changes
[ ] CI-related changes
[ ] Documentation content changes
[ ] Application / infrastructure changes
[ ] Other:

What Is the Current Behavior?

At this moment when we have more than one error we are showing an warning on browser console. This is a problem in the quick order because when we have more than one product with error/errors we dont show feedback to the customer.
Also when we are showing the error we dont know which product we are having the error.

What Is the New Behavior?

With this change we are fixing two problems

  • Show error when we have more than one
  • Have the possibility to know which product is having an error.

We are adding a property named causes to the HttpError. This property will have the error message with more details and if it has will have the product sku.

Examples
Quick order when we are trying to add two products
quickorder_tworproducts

Does this PR Introduce a Breaking Change?

[ ] Yes
[ X] No

Other Information

@dhhyi dhhyi requested review from SGrueber and dhhyi April 12, 2022 07:44
dhhyi
dhhyi previously approved these changes Apr 12, 2022
@dhhyi dhhyi self-requested a review April 13, 2022 10:01
@dhhyi dhhyi dismissed their stale review April 13, 2022 10:01

partial case not mapped yet

dhhyi
dhhyi previously approved these changes Apr 20, 2022
@SGrueber SGrueber self-assigned this Apr 25, 2022
@SGrueber SGrueber added this to the 2.3 milestone Apr 25, 2022
@SGrueber SGrueber requested a review from M-Behr April 25, 2022 08:03
@SGrueber SGrueber force-pushed the feat--map-error-messages-on-object branch from d3dbd18 to 68a3bd8 Compare April 25, 2022 09:32
@M-Behr
Copy link

M-Behr commented Apr 25, 2022

Thank you for your feedback. I see 3 variants to improve the error case behavior:

Var 1:
2 products could not be added. (--> general error)
The product quantity for these items in your cart... (--> reason summary for same errors)

Var 2:
2 products could not be added. (--> general error)
The product quantity for "Microsoft Surface Hub" in your shopping cart... (--> reason 1)
The product quantity for "Microsoft Surface Book" in your shopping cart... (--> reason 2)

Alternative: The product quantity for product with SKU "123456" in your shopping cart...
(Is this really helpful because we don't show SKUs in mini cart?)

Var 3:
If error handling is hard to overview in mini cart, we could display always shopping cart page in cases of errors or adjustments (see Wireframes).
image

We will check your solution and discuss if it's fits to our interaction guidelines.

@M-Behr
Copy link

M-Behr commented Apr 25, 2022

I discussed the error behavior with @SGrueber.
We want to jump to the cart page if we get multiple product errors after adding products to the cart. There we can display the individual errors directly on the product and make it much clearer. It should be look like that:

2022-04-25 13_41_10-Failed Inventory Check

We would continue to display error messages for a single product in the mini shopping cart. We would leave the behavior for this case as it is.

@ivopereira15 @dhhyi Is this behavior fine for you guys?

@dhhyi
Copy link
Collaborator

dhhyi commented Apr 25, 2022

@M-Behr Yes, the main goal for us is that errors are mapped and available, so if that part of the PR is okay, we are good. We have customized the display in our project using toasts 😉
@SGrueber Will you take care of the behavior for the standard PWA?

cc @ivopereira15

@SGrueber
Copy link
Collaborator

Yes, I will

@shauke shauke modified the milestones: 2.3, 2.4 May 3, 2022
@SGrueber SGrueber force-pushed the feat--map-error-messages-on-object branch from 20fc4a9 to 795c913 Compare May 4, 2022 08:10
@SGrueber
Copy link
Collaborator

SGrueber commented May 5, 2022

The error display in the mini basket looks like this now:

image

@MaxKless
Copy link
Collaborator

MaxKless commented May 5, 2022

Hi @ivopereira15, can you let me know why you used the info basket substate to track the errors & causes? Instead of the error substate?
It would seem a bit cleaner that way but maybe that comes with some additional disadvantages. Could you provide some context?

M-Behr
M-Behr previously approved these changes May 5, 2022
@ivopereira15
Copy link
Author

ivopereira15 commented May 5, 2022

Hi all. @MaxKless

The error substate its working only when you have a bad request. Like a Status Code: 422 Unprocessable Entity. This is a clear error message that will be handled by addItemsToBasketFail

Lets imagine in the quickorder (that was one the problems that we found) we are trying to add to cart two products. One that we will have an error and other will be success. The response is Status Code: 207 Multi-Status.
That means we are not mapping to an error. We are going to theaddItemsToBasketSuccess action and mapping to an info object.

here what we receive from the request.
image

What i did was put that error inside the infos object. Since we already were showing alert/info error using the info object, could be a good idea to show the error too.
With that infos object we have the info and the errors on the same place.

@SGrueber SGrueber requested review from MaxKless and removed request for SGrueber May 6, 2022 13:53
@MaxKless MaxKless modified the milestones: 2.4, 3.0 May 31, 2022

export interface BasketInfo {
causes?: BasketFeedback[];
code: string;
message: string;
error?: ErrorFeedback[];
Copy link
Collaborator

Choose a reason for hiding this comment

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

since this is an array, it should be called errors imo.

@@ -10,4 +23,6 @@ export interface HttpError {

/** human readable (and localized) error message */
message?: string;

causes?: ErrorFeedback[];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be a documented property like the others.
I also think it would be good to rename the property - see comment on mini-basket-content.component.html

*/
@Component({
selector: 'ish-shopping-basket-error-message',
template: '',
Copy link
Collaborator

Choose a reason for hiding this comment

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

Having a component without a template isn't very nice. Something is created in the DOM but only used for state management, kind of like an effect.
Since I understand that this logic is component-specific and doesn't belong in an effect, I would extract the logic to the parent component (shopping-basket.component) and subscribing there or using rx state's hold method to to trigger a component state side-effect like the context facades do it.

if (infoError) {
infoError?.map(error => {
this.messageFacade.error({
message: `<b>${error.message}</b> - ${error.causes?.[0].message} ${error.causes?.[0].parameters?.sku}`,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you provide some insight as to why only the first error is dispatched here?

<ng-container *ngIf="error.causes as productCauses">
<div *ngFor="let productCause of productCauses" class="text-danger">
<strong>{{ productCause.message }}</strong>
<ng-container *ngIf="productCause.causes as causes">
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the naming could be improved here. The fact that theres two nested causesproperties in the model really makes this code incredibly hard to read and confusing. Since the top-levelcausesproperty is of typeErrorFeedback`, maybe the naming could be similar to that?
What do you think?

when(checkoutFacade.basketInfoError$).thenReturn(of(undefined));
});

it('should be created', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the behavior currently defined in the component is pretty straightforward to test and we should probably do so wherever it ends up.

@@ -85,6 +85,7 @@ export class CheckoutFacade {
basketChange$ = this.basketChangeInternal$.asObservable();
basketError$ = this.store.pipe(select(getBasketError));
basketInfo$ = this.store.pipe(select(getBasketInfo));
basketInfoError$ = this.basketInfo$.pipe(map(info => (info?.length ? info[0].error : undefined)));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe this should be its own selector?

Also, maybe this is the wrong place to ask this so please let me know if that's the case but can you explain the store structure here a bit? @SGrueber
image

How come there's both a basket.info as well as a info substate in the basket state?

Copy link
Collaborator

Choose a reason for hiding this comment

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

basket.info contains info of the get basket (or the result of any call that returns the whole basket ). The info sub state contains the info of the last basket operation, e.g. addProductToCart. Because after each basket operation a get basket is triggered we need both info values.

@SGrueber SGrueber force-pushed the feat--map-error-messages-on-object branch from 067ef0c to d867ffa Compare July 29, 2022 09:58
SGrueber added a commit that referenced this pull request Aug 2, 2022
Co-authored-by: Silke Grueber <s.grueber@intershop.de>
SGrueber added a commit that referenced this pull request Aug 2, 2022
Co-authored-by: Silke Grueber <s.grueber@intershop.de>
@SGrueber
Copy link
Collaborator

SGrueber commented Aug 2, 2022

has been merged by #1230

@SGrueber SGrueber closed this Aug 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants