Skip to content

Commit

Permalink
Merge origin/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
rmch91 committed Oct 8, 2024
2 parents 04bb8aa + 10ad84c commit 3ea7c09
Show file tree
Hide file tree
Showing 76 changed files with 1,065 additions and 240 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
</ng-container>

<button
#addToCartDialogTriggerEl
*ngIf="hasStock"
[ngClass]="
options?.displayAddToCart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import {
ChangeDetectorRef,
Component,
ComponentRef,
ElementRef,
HostListener,
Input,
OnDestroy,
OnInit,
Optional,
ViewChild,
inject,
} from '@angular/core';
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
Expand Down Expand Up @@ -55,6 +57,11 @@ export class AddToCartComponent implements OnInit, OnDestroy {
*/
@Input() product: Product;

/**
* Element responsible for opening the modal. The reference is used to refocus the modal after it closes.
*/
@ViewChild('addToCartDialogTriggerEl') addToCartDialogTriggerEl: ElementRef;

maxQuantity: number;

hasStock: boolean = false;
Expand All @@ -77,9 +84,7 @@ export class AddToCartComponent implements OnInit, OnDestroy {

iconTypes = ICON_TYPE;

@Optional() featureConfigService = inject(FeatureConfigService, {
optional: true,
});
private featureConfigService = inject(FeatureConfigService);

/**
* We disable the dialog launch on quantity input,
Expand Down Expand Up @@ -228,6 +233,9 @@ export class AddToCartComponent implements OnInit, OnDestroy {
newEvent.quantity = quantity;
newEvent.numberOfEntriesBeforeAdd = numberOfEntriesBeforeAdd;
newEvent.pickupStoreName = storeName;
if (this.featureConfigService.isEnabled('a11yDialogTriggerRefocus')) {
newEvent.triggerElementRef = this.addToCartDialogTriggerEl;
}
return newEvent;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class AddedToCartDialogEventListener implements OnDestroy {

const dialog = this.launchDialogService.openDialog(
LAUNCH_CALLER.ADDED_TO_CART,
undefined,
event?.triggerElementRef,
undefined,
addToCartData
);
Expand Down
6 changes: 6 additions & 0 deletions feature-libs/cart/base/root/events/cart.events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { ElementRef } from '@angular/core';
import { CxEvent } from '@spartacus/core';
import { OrderEntry } from '../models/cart.model';

Expand Down Expand Up @@ -127,6 +128,11 @@ export class CartUiEventAddToCart extends CxEvent {
quantity: number;
numberOfEntriesBeforeAdd: number;
pickupStoreName?: string;
/**
* Since the event can be used to open a dialog, we need to know which element triggered it.
* This way we can refocus on it after the dialog is closed.
*/
triggerElementRef?: ElementRef;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
[selectedOption]="pickupOption$ | async"
[displayPickupLocation]="displayPickupLocation$ | async"
(pickupOptionChange)="onPickupOptionChange($event)"
(pickupLocationChange)="openDialog()"
(pickupLocationChange)="openDialog($event)"
></cx-pickup-options>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { CommonModule } from '@angular/common';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { I18nTestingModule, Product } from '@spartacus/core';
import {
FeatureConfigService,
I18nTestingModule,
Product,
} from '@spartacus/core';

import {
AugmentedPointOfService,
Expand All @@ -13,8 +17,8 @@ import {
} from '@spartacus/pickup-in-store/root';
import {
CurrentProductService,
LaunchDialogService,
LAUNCH_CALLER,
LaunchDialogService,
} from '@spartacus/storefront';
import { Observable, of, Subscription } from 'rxjs';
import { PdpPickupOptionsContainerComponent } from './pdp-pickup-options-container.component';
Expand Down Expand Up @@ -80,6 +84,12 @@ class MockCurrentLocationService {
}
}

class MockFeatureConfigService {
isEnabled() {
return true;
}
}

describe('PdpPickupOptionsComponent', () => {
let component: PdpPickupOptionsContainerComponent;
let fixture: ComponentFixture<PdpPickupOptionsContainerComponent>;
Expand Down Expand Up @@ -118,6 +128,10 @@ describe('PdpPickupOptionsComponent', () => {
provide: CurrentLocationService,
useClass: MockCurrentLocationService,
},
{
provide: FeatureConfigService,
useClass: MockFeatureConfigService,
},
],
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
import {
Component,
ElementRef,
inject,
OnDestroy,
OnInit,
ViewChild,
ViewContainerRef,
} from '@angular/core';
import { Product } from '@spartacus/core';
import { FeatureConfigService, Product } from '@spartacus/core';

import {
AugmentedPointOfService,
Expand All @@ -26,8 +27,8 @@ import {
} from '@spartacus/pickup-in-store/root';
import {
CurrentProductService,
LaunchDialogService,
LAUNCH_CALLER,
LaunchDialogService,
} from '@spartacus/storefront';
import { combineLatest, iif, Observable, of, Subscription } from 'rxjs';
import {
Expand Down Expand Up @@ -55,6 +56,12 @@ function isProductWithCode(
templateUrl: 'pdp-pickup-options-container.component.html',
})
export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
// TODO: Remove element reference once 'a11yDialogTriggerRefocus' feature flag is removed.
/**
* @deprecated since 2211.28.0
* This reference does not point to any element and will be removed at earliest convinience.
* The 'triggerElement' is passed through 'PickupOptionChange' event instead.
*/
@ViewChild('open') element: ElementRef;
subscription = new Subscription();

Expand All @@ -65,6 +72,7 @@ export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
private productCode: string;
private displayNameIsSet = false;

private featureConfigService = inject(FeatureConfigService);
constructor(
protected currentProductService: CurrentProductService,
protected intendedPickupLocationService: IntendedPickupLocationFacade,
Expand Down Expand Up @@ -160,10 +168,17 @@ export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
this.subscription.unsubscribe();
}

openDialog(): void {
// TODO: Make argument required once 'a11yDialogTriggerRefocus' feature flag is removed.
/**
* @deprecated since 2211.28.0 - The use of TriggerElement param will become mandatory.
* @param triggerElement - The reference of element that triggered the dialog. Used to refocus on it after the dialog is closed.
*/
openDialog(triggerElement?: ElementRef): void {
const dialog = this.launchDialogService.openDialog(
LAUNCH_CALLER.PICKUP_IN_STORE,
this.element,
this.featureConfigService.isEnabled('a11yDialogTriggerRefocus')
? triggerElement
: this.element,
this.vcr,
{ productCode: this.productCode }
);
Expand All @@ -173,16 +188,46 @@ export class PdpPickupOptionsContainerComponent implements OnInit, OnDestroy {
}
}

onPickupOptionChange(option: PickupOption) {
this.intendedPickupLocationService.setPickupOption(
this.productCode,
option
);
if (option === 'delivery') {
return;
}
if (!this.displayNameIsSet) {
this.openDialog();
// TODO: Remove 'PickupOption' argument type once 'a11yDialogTriggerRefocus' feature flag is removed.
/**
* @deprecated since 2211.28.0 - Use event param instead of option.
* @param event - Object containing the selected option and the element that triggered the change.
*/
onPickupOptionChange(option: PickupOption): void;
// eslint-disable-next-line @typescript-eslint/unified-signatures
onPickupOptionChange(event: {
option: PickupOption;
triggerElement: ElementRef;
}): void;
onPickupOptionChange(
event: { option: PickupOption; triggerElement: ElementRef } | PickupOption
): void {
if (
this.featureConfigService.isEnabled('a11yDialogTriggerRefocus') &&
typeof event === 'object'
) {
const { option, triggerElement = undefined } = event;
this.intendedPickupLocationService.setPickupOption(
this.productCode,
option
);
if (option === 'delivery') {
return;
}
if (!this.displayNameIsSet) {
this.openDialog(triggerElement);
}
} else if (typeof event === 'string') {
this.intendedPickupLocationService.setPickupOption(
this.productCode,
event
);
if (event === 'delivery') {
return;
}
if (!this.displayNameIsSet) {
this.openDialog();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
|
<button
*cxFeature="'a11yUseButtonsForBtnLinks'"
#dialogTriggerEl
[attr.data-store-location-link]="
displayPickupLocation ? 'change' : 'select'
"
Expand All @@ -59,6 +60,7 @@
<a
*cxFeature="'!a11yUseButtonsForBtnLinks'"
role="button"
#dialogTriggerEl
[attr.data-store-location-link]="
displayPickupLocation ? 'change' : 'select'
"
Expand Down Expand Up @@ -119,6 +121,7 @@
|
<button
*cxFeature="'a11yUseButtonsForBtnLinks'"
#dialogTriggerEl
[attr.data-store-location-link]="
displayPickupLocation ? 'change' : 'select'
"
Expand All @@ -134,6 +137,7 @@
</button>
<a
*cxFeature="'!a11yUseButtonsForBtnLinks'"
#dialogTriggerEl
role="button"
[attr.data-store-location-link]="
displayPickupLocation ? 'change' : 'select'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { I18nTestingModule } from '@spartacus/core';
import { FeatureConfigService, I18nTestingModule } from '@spartacus/core';
import { PickupOption } from '@spartacus/pickup-in-store/root';
import { MockFeatureDirective } from 'projects/storefrontlib/shared/test/mock-feature-directive';
import { Observable } from 'rxjs';
import { PickupOptionsComponent } from './pickup-options.component';

class MockFeatureConfigService {
isEnabled() {
return true;
}
}

describe('PickupOptionsComponent', () => {
let component: PickupOptionsComponent;
let fixture: ComponentFixture<PickupOptionsComponent>;
Expand All @@ -16,6 +22,9 @@ describe('PickupOptionsComponent', () => {
TestBed.configureTestingModule({
declarations: [PickupOptionsComponent, MockFeatureDirective],
imports: [CommonModule, I18nTestingModule, ReactiveFormsModule],
providers: [
{ provide: FeatureConfigService, useClass: MockFeatureConfigService },
],
});
fixture = TestBed.createComponent(PickupOptionsComponent);
component = fixture.componentInstance;
Expand Down Expand Up @@ -43,7 +52,10 @@ describe('PickupOptionsComponent', () => {
spyOn(component.pickupOptionChange, 'emit');
component.onPickupOptionChange('delivery');

expect(component.pickupOptionChange.emit).toHaveBeenCalledWith('delivery');
expect(component.pickupOptionChange.emit).toHaveBeenCalledWith({
option: 'delivery',
triggerElement: component.triggerElement,
});
});

it('should emit on onPickupLocationChange', () => {
Expand Down
Loading

0 comments on commit 3ea7c09

Please sign in to comment.