From 0b2dafdeafd54672fbb63e7c8078a5e1da46e1d3 Mon Sep 17 00:00:00 2001 From: Christoph Hinssen Date: Mon, 24 Jul 2023 11:00:17 +0200 Subject: [PATCH 1/6] introduce guard to change routing targets if quote cart is active --- .../cart/base/root/cart-base-root.module.ts | 3 +- feature-libs/cart/base/root/guards/index.ts | 8 ++++ .../cart/base/root/guards/quote-cart.guard.ts | 39 +++++++++++++++++++ .../base/root/guards/quote-cart.service.ts | 32 +++++++++++++++ feature-libs/cart/base/root/public_api.ts | 1 + .../checkout-orchestrator.module.ts | 8 +++- .../quote-added-to-cart-event.listener.ts | 38 ++++++++++++++++++ .../quote/core/facade/quote.service.ts | 14 ++++++- feature-libs/quote/core/quote-core.module.ts | 7 +++- 9 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 feature-libs/cart/base/root/guards/index.ts create mode 100644 feature-libs/cart/base/root/guards/quote-cart.guard.ts create mode 100644 feature-libs/cart/base/root/guards/quote-cart.service.ts create mode 100644 feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts diff --git a/feature-libs/cart/base/root/cart-base-root.module.ts b/feature-libs/cart/base/root/cart-base-root.module.ts index 0c0bd9307bc..699e058ded3 100644 --- a/feature-libs/cart/base/root/cart-base-root.module.ts +++ b/feature-libs/cart/base/root/cart-base-root.module.ts @@ -22,6 +22,7 @@ import { MINI_CART_FEATURE, } from './feature-name'; import { ActiveCartOrderEntriesContextToken } from './tokens/context'; +import { QuoteCartGuard } from './guards/quote-cart.guard'; export function defaultCartComponentsConfig() { const config = { @@ -63,7 +64,7 @@ export function defaultCartComponentsConfig() { { // @ts-ignore path: null, - canActivate: [CmsPageGuard], + canActivate: [CmsPageGuard, QuoteCartGuard], component: PageLayoutComponent, data: { cxRoute: 'cart', diff --git a/feature-libs/cart/base/root/guards/index.ts b/feature-libs/cart/base/root/guards/index.ts new file mode 100644 index 00000000000..1b9a98f2d4a --- /dev/null +++ b/feature-libs/cart/base/root/guards/index.ts @@ -0,0 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2023 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './quote-cart.service'; +export * from './quote-cart.guard'; diff --git a/feature-libs/cart/base/root/guards/quote-cart.guard.ts b/feature-libs/cart/base/root/guards/quote-cart.guard.ts new file mode 100644 index 00000000000..e4046ae0c43 --- /dev/null +++ b/feature-libs/cart/base/root/guards/quote-cart.guard.ts @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2023 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Injectable } from '@angular/core'; +import { CanActivate, Router, UrlTree } from '@angular/router'; + +import { Observable, combineLatest } from 'rxjs'; +import { QuoteCartService } from './quote-cart.service'; +import { map } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root', +}) +export class QuoteCartGuard implements CanActivate { + constructor( + protected router: Router, + protected quoteCartService: QuoteCartService + ) { + this.quoteCartService.setQuoteCartActive(false); + this.quoteCartService.setQuoteId(''); + } + canActivate(): Observable { + return combineLatest([ + this.quoteCartService.getQuoteCartActive(), + this.quoteCartService.getQuoteId(), + ]).pipe( + map(([isQuoteCartActive, quoteId]) => { + if (isQuoteCartActive) { + this.router.navigateByUrl('my-account/quote/' + quoteId); + return false; + } + return true; + }) + ); + } +} diff --git a/feature-libs/cart/base/root/guards/quote-cart.service.ts b/feature-libs/cart/base/root/guards/quote-cart.service.ts new file mode 100644 index 00000000000..786645e1e61 --- /dev/null +++ b/feature-libs/cart/base/root/guards/quote-cart.service.ts @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2023 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Injectable } from '@angular/core'; +import { Observable, ReplaySubject } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class QuoteCartService { + private quoteId: Observable = new ReplaySubject(1); + private quoteCartActive: Observable = new ReplaySubject(1); + + public setQuoteId(expMode: string): void { + (this.quoteId as ReplaySubject).next(expMode); + } + + public getQuoteId(): Observable { + return this.quoteId; + } + + public setQuoteCartActive(expMode: boolean): void { + (this.quoteCartActive as ReplaySubject).next(expMode); + } + + public getQuoteCartActive(): Observable { + return this.quoteCartActive; + } +} diff --git a/feature-libs/cart/base/root/public_api.ts b/feature-libs/cart/base/root/public_api.ts index 1288c8c226f..24fb2202718 100644 --- a/feature-libs/cart/base/root/public_api.ts +++ b/feature-libs/cart/base/root/public_api.ts @@ -12,6 +12,7 @@ export * from './facade/index'; export * from './feature-name'; export * from './models/index'; export * from './tokens/index'; +export * from './guards/index'; /** AUGMENTABLE_TYPES_START */ export { Cart, DeliveryMode, OrderEntry } from './models/cart.model'; diff --git a/feature-libs/checkout/base/components/checkout-orchestrator/checkout-orchestrator.module.ts b/feature-libs/checkout/base/components/checkout-orchestrator/checkout-orchestrator.module.ts index 34543a54f59..cf6d8299ddb 100644 --- a/feature-libs/checkout/base/components/checkout-orchestrator/checkout-orchestrator.module.ts +++ b/feature-libs/checkout/base/components/checkout-orchestrator/checkout-orchestrator.module.ts @@ -11,6 +11,7 @@ import { CartNotEmptyGuard } from '../guards/cart-not-empty.guard'; import { CheckoutAuthGuard } from '../guards/checkout-auth.guard'; import { CheckoutGuard } from '../guards/checkout.guard'; import { CheckoutOrchestratorComponent } from './checkout-orchestrator.component'; +import { QuoteCartGuard } from '@spartacus/cart/base/root'; @NgModule({ imports: [CommonModule], @@ -19,7 +20,12 @@ import { CheckoutOrchestratorComponent } from './checkout-orchestrator.component cmsComponents: { CheckoutOrchestrator: { component: CheckoutOrchestratorComponent, - guards: [CheckoutAuthGuard, CartNotEmptyGuard, CheckoutGuard], + guards: [ + QuoteCartGuard, + CheckoutAuthGuard, + CartNotEmptyGuard, + CheckoutGuard, + ], }, }, }), diff --git a/feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts b/feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts new file mode 100644 index 00000000000..d00dff76c9d --- /dev/null +++ b/feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2023 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Injectable, OnDestroy } from '@angular/core'; +import { CartUiEventAddToCart } from '@spartacus/cart/base/root'; +import { EventService } from '@spartacus/core'; +import { QuoteDetailsReloadQueryEvent } from '@spartacus/quote/root'; +import { LaunchDialogService } from '@spartacus/storefront'; +import { Subscription } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class QuoteAddedToCartEventListener implements OnDestroy { + protected subscription = new Subscription(); + + constructor( + protected eventService: EventService, + protected launchDialogService: LaunchDialogService + ) { + this.onAddToCart(); + } + + protected onAddToCart() { + this.subscription.add( + this.eventService.get(CartUiEventAddToCart).subscribe(() => { + this.eventService.dispatch({}, QuoteDetailsReloadQueryEvent); + }) + ); + } + + ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } +} diff --git a/feature-libs/quote/core/facade/quote.service.ts b/feature-libs/quote/core/facade/quote.service.ts index 15ba53751ed..0e09d74860d 100644 --- a/feature-libs/quote/core/facade/quote.service.ts +++ b/feature-libs/quote/core/facade/quote.service.ts @@ -5,7 +5,11 @@ */ import { Injectable } from '@angular/core'; -import { ActiveCartFacade, MultiCartFacade } from '@spartacus/cart/base/root'; +import { + ActiveCartFacade, + MultiCartFacade, + QuoteCartService, +} from '@spartacus/cart/base/root'; import { Comment, QuoteFacade, @@ -86,6 +90,8 @@ export class QuoteService implements QuoteFacade { active: true, }, }); + this.quoteCartService.setQuoteCartActive(true); + this.quoteCartService.setQuoteId(quote.code); this.eventService.dispatch({}, QuoteDetailsReloadQueryEvent); }), map(([_, _userId, quote]) => quote) @@ -159,6 +165,9 @@ export class QuoteService implements QuoteFacade { tap(() => { this.isActionPerforming$.next(false); this.eventService.dispatch({}, QuoteDetailsReloadQueryEvent); + if (payload.quoteAction === QuoteActionType.SUBMIT) { + this.quoteCartService.setQuoteCartActive(false); + } }) ); }, @@ -244,7 +253,8 @@ export class QuoteService implements QuoteFacade { protected commandService: CommandService, protected activeCartService: ActiveCartFacade, protected routingService: RoutingService, - protected multiCartService: MultiCartFacade + protected multiCartService: MultiCartFacade, + protected quoteCartService: QuoteCartService ) {} createQuote(quoteMetadata: QuoteMetadata): Observable { diff --git a/feature-libs/quote/core/quote-core.module.ts b/feature-libs/quote/core/quote-core.module.ts index b99f39b822e..e3984e92cc2 100644 --- a/feature-libs/quote/core/quote-core.module.ts +++ b/feature-libs/quote/core/quote-core.module.ts @@ -9,6 +9,7 @@ import { HttpErrorHandler } from '@spartacus/core'; import { QuoteConnector } from './connectors/quote.connector'; import { facadeProviders } from './facade/facade-providers'; import { QuoteBadRequestHandler } from './http-interceptors/quote-bad-request.handler'; +import { QuoteAddedToCartEventListener } from './event/quote-added-to-cart-event.listener'; @NgModule({ providers: [ @@ -21,4 +22,8 @@ import { QuoteBadRequestHandler } from './http-interceptors/quote-bad-request.ha }, ], }) -export class QuoteCoreModule {} +export class QuoteCoreModule { + constructor(_quoteAddedToCartEventListener: QuoteAddedToCartEventListener) { + // Intentional empty constructor + } +} From 3d8ac30837e8d441d40d7f09b1fca185e308e205 Mon Sep 17 00:00:00 2001 From: Christoph Hinssen Date: Mon, 24 Jul 2023 12:54:01 +0200 Subject: [PATCH 2/6] Enable edit action for buyer --- .../quote-actions-by-role/quote-actions-by-role.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts b/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts index e6f267daca8..b9252d05189 100644 --- a/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts +++ b/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts @@ -28,7 +28,7 @@ import { QuoteActionsByRoleComponent } from './quote-actions-by-role.component'; QuoteActionType.SUBMIT, ], actionsOrderByState: { - BUYER_DRAFT: [QuoteActionType.CANCEL, QuoteActionType.SUBMIT], + BUYER_DRAFT: [QuoteActionType.CANCEL, QuoteActionType.EDIT, QuoteActionType.SUBMIT], BUYER_OFFER: [ QuoteActionType.CANCEL, QuoteActionType.EDIT, From afe8c2fa92a11b8a1d353040c5bed132dcbc524d Mon Sep 17 00:00:00 2001 From: Christoph Hinssen Date: Mon, 24 Jul 2023 13:29:25 +0200 Subject: [PATCH 3/6] tmp --- .../occ/converters/occ-quote-action-normalizer.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts index c8d4a9bae8c..a893b43f5d9 100644 --- a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts +++ b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts @@ -5,6 +5,7 @@ */ import { Injectable } from '@angular/core'; +import { QuoteCartService } from '@spartacus/cart/base/root'; import { Converter } from '@spartacus/core'; import { QuoteCoreConfig } from '@spartacus/quote/core'; import { @@ -14,10 +15,12 @@ import { QuoteActionType, QuoteState, } from '@spartacus/quote/root'; +import { combineLatest } from 'rxjs'; +import { take } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class OccQuoteActionNormalizer implements Converter { - constructor(protected quoteConfig: QuoteCoreConfig) {} + constructor(protected quoteConfig: QuoteCoreConfig, protected quoteCartService: QuoteCartService) {} convert(source: OccQuote, target?: Quote): Quote { if (!target) { @@ -27,7 +30,7 @@ export class OccQuoteActionNormalizer implements Converter { if (source.allowedActions && source.state) { target.allowedActions = this.getOrderedActions( source.state, - source.allowedActions + source.allowedActions, source.code ).map((action) => this.getActionCategory(action)); } const switchToEditModeRequired = target.allowedActions?.find( @@ -52,8 +55,12 @@ export class OccQuoteActionNormalizer implements Converter { return { type, isPrimary: primaryActions.includes(type) }; } - protected getOrderedActions(state: QuoteState, list: QuoteActionType[]) { + protected getOrderedActions(state: QuoteState, list: QuoteActionType[], quoteId: string) { const order = this.quoteConfig.quote?.actions?.actionsOrderByState?.[state]; + // combineLatest([this.quoteCartService.getQuoteCartActive(),this.quoteCartService.getQuoteId]).pipe( + // take(1)).subscribe(([a,b])=> { + // if (a) + // }); return order ? list From 274c228b51c90905f3760aa544fc1e2a743ba593 Mon Sep 17 00:00:00 2001 From: Christoph Hinssen Date: Mon, 24 Jul 2023 16:37:14 +0200 Subject: [PATCH 4/6] continue with quote spike --- .../cart/base/root/guards/quote-cart.guard.ts | 15 +++--- .../base/root/guards/quote-cart.service.ts | 13 +++-- .../quote/core/facade/quote.service.ts | 21 +++++++- .../converters/occ-quote-action-normalizer.ts | 50 ++++++++++++++----- 4 files changed, 73 insertions(+), 26 deletions(-) diff --git a/feature-libs/cart/base/root/guards/quote-cart.guard.ts b/feature-libs/cart/base/root/guards/quote-cart.guard.ts index e4046ae0c43..879f45bb537 100644 --- a/feature-libs/cart/base/root/guards/quote-cart.guard.ts +++ b/feature-libs/cart/base/root/guards/quote-cart.guard.ts @@ -5,23 +5,21 @@ */ import { Injectable } from '@angular/core'; -import { CanActivate, Router, UrlTree } from '@angular/router'; +import { CanActivate, UrlTree } from '@angular/router'; import { Observable, combineLatest } from 'rxjs'; import { QuoteCartService } from './quote-cart.service'; import { map } from 'rxjs/operators'; +import { RoutingService } from '@spartacus/core'; @Injectable({ providedIn: 'root', }) export class QuoteCartGuard implements CanActivate { constructor( - protected router: Router, + protected routingService: RoutingService, protected quoteCartService: QuoteCartService - ) { - this.quoteCartService.setQuoteCartActive(false); - this.quoteCartService.setQuoteId(''); - } + ) {} canActivate(): Observable { return combineLatest([ this.quoteCartService.getQuoteCartActive(), @@ -29,7 +27,10 @@ export class QuoteCartGuard implements CanActivate { ]).pipe( map(([isQuoteCartActive, quoteId]) => { if (isQuoteCartActive) { - this.router.navigateByUrl('my-account/quote/' + quoteId); + this.routingService.go({ + cxRoute: 'quoteDetails', + params: { quoteId: quoteId }, + }); return false; } return true; diff --git a/feature-libs/cart/base/root/guards/quote-cart.service.ts b/feature-libs/cart/base/root/guards/quote-cart.service.ts index 786645e1e61..f89c679fe6e 100644 --- a/feature-libs/cart/base/root/guards/quote-cart.service.ts +++ b/feature-libs/cart/base/root/guards/quote-cart.service.ts @@ -14,16 +14,21 @@ export class QuoteCartService { private quoteId: Observable = new ReplaySubject(1); private quoteCartActive: Observable = new ReplaySubject(1); - public setQuoteId(expMode: string): void { - (this.quoteId as ReplaySubject).next(expMode); + constructor() { + (this.quoteCartActive as ReplaySubject).next(false); + (this.quoteId as ReplaySubject).next(''); + } + + public setQuoteId(quoteId: string): void { + (this.quoteId as ReplaySubject).next(quoteId); } public getQuoteId(): Observable { return this.quoteId; } - public setQuoteCartActive(expMode: boolean): void { - (this.quoteCartActive as ReplaySubject).next(expMode); + public setQuoteCartActive(quoteCartActive: boolean): void { + (this.quoteCartActive as ReplaySubject).next(quoteCartActive); } public getQuoteCartActive(): Observable { diff --git a/feature-libs/quote/core/facade/quote.service.ts b/feature-libs/quote/core/facade/quote.service.ts index 0e09d74860d..6ded67f604b 100644 --- a/feature-libs/quote/core/facade/quote.service.ts +++ b/feature-libs/quote/core/facade/quote.service.ts @@ -111,6 +111,7 @@ export class QuoteService implements QuoteFacade { (payload) => this.userIdService.takeUserId().pipe( take(1), + switchMap((userId) => this.quoteConnector.editQuote( userId, @@ -206,8 +207,24 @@ export class QuoteService implements QuoteFacade { this.routingService.getRouterState().pipe( withLatestFrom(this.userIdService.takeUserId()), switchMap(([{ state }, userId]) => - this.quoteConnector.getQuote(userId, state.params.quoteId) - ) + zip( + this.quoteConnector.getQuote(userId, state.params.quoteId), + of(userId) + ) + ), + //TODO CHHI only if user explictly triggered edit for this quote + tap(([quote, userId]) => { + this.multiCartService.loadCart({ + userId: userId, + cartId: quote.cartId as string, + extraData: { + active: true, + }, + }); + this.quoteCartService.setQuoteCartActive(true); + this.quoteCartService.setQuoteId(quote.code); + }), + map(([quote, _]) => quote) ), { reloadOn: [QuoteDetailsReloadQueryEvent, LoginEvent], diff --git a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts index a893b43f5d9..6e7f4bff484 100644 --- a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts +++ b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts @@ -20,7 +20,10 @@ import { take } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class OccQuoteActionNormalizer implements Converter { - constructor(protected quoteConfig: QuoteCoreConfig, protected quoteCartService: QuoteCartService) {} + constructor( + protected quoteConfig: QuoteCoreConfig, + protected quoteCartService: QuoteCartService + ) {} convert(source: OccQuote, target?: Quote): Quote { if (!target) { @@ -30,7 +33,8 @@ export class OccQuoteActionNormalizer implements Converter { if (source.allowedActions && source.state) { target.allowedActions = this.getOrderedActions( source.state, - source.allowedActions, source.code + source.allowedActions, + source.code ).map((action) => this.getActionCategory(action)); } const switchToEditModeRequired = target.allowedActions?.find( @@ -55,17 +59,37 @@ export class OccQuoteActionNormalizer implements Converter { return { type, isPrimary: primaryActions.includes(type) }; } - protected getOrderedActions(state: QuoteState, list: QuoteActionType[], quoteId: string) { + protected getOrderedActions( + state: QuoteState, + list: QuoteActionType[], + quoteId: string + ) { const order = this.quoteConfig.quote?.actions?.actionsOrderByState?.[state]; - // combineLatest([this.quoteCartService.getQuoteCartActive(),this.quoteCartService.getQuoteId]).pipe( - // take(1)).subscribe(([a,b])=> { - // if (a) - // }); - - return order - ? list - .filter((item) => order.includes(item)) - .sort((a, b) => order.indexOf(a) - order.indexOf(b)) - : list; + if (order) { + //deep copy order list + const clonedActionList = order.map((actionType) => actionType); + combineLatest([ + this.quoteCartService.getQuoteCartActive(), + this.quoteCartService.getQuoteId(), + ]) + .pipe(take(1)) + .subscribe(([isQuoteCartActive, cartQuoteId]) => { + console.log('CHHI cart quote id: ' + cartQuoteId); + console.log('CHHI current quote id: ' + quoteId); + if (isQuoteCartActive && cartQuoteId === quoteId) { + const editIndex = clonedActionList.indexOf(QuoteActionType.EDIT); + if (editIndex > -1) { + clonedActionList.splice(editIndex, 1); + } + } + }); + return list + .filter((item) => clonedActionList.includes(item)) + .sort( + (a, b) => clonedActionList.indexOf(a) - clonedActionList.indexOf(b) + ); + } else { + return list; + } } } From 3637d3aea811fb5710e5c66f67d9b8245b308148 Mon Sep 17 00:00:00 2001 From: Christoph Hinssen Date: Mon, 24 Jul 2023 16:37:42 +0200 Subject: [PATCH 5/6] Update quote-actions-by-role.module.ts --- .../quote-actions-by-role/quote-actions-by-role.module.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts b/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts index b9252d05189..328b2494edc 100644 --- a/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts +++ b/feature-libs/quote/components/quote-actions-by-role/quote-actions-by-role.module.ts @@ -28,7 +28,11 @@ import { QuoteActionsByRoleComponent } from './quote-actions-by-role.component'; QuoteActionType.SUBMIT, ], actionsOrderByState: { - BUYER_DRAFT: [QuoteActionType.CANCEL, QuoteActionType.EDIT, QuoteActionType.SUBMIT], + BUYER_DRAFT: [ + QuoteActionType.CANCEL, + QuoteActionType.EDIT, + QuoteActionType.SUBMIT, + ], BUYER_OFFER: [ QuoteActionType.CANCEL, QuoteActionType.EDIT, From 88ff18b900b2bdc85b3f01a44368e4e446bec087 Mon Sep 17 00:00:00 2001 From: Christoph Hinssen Date: Tue, 25 Jul 2023 09:14:19 +0200 Subject: [PATCH 6/6] Fix tests --- ...quote-added-to-cart-event.listener.spec.ts | 51 +++++++++++++++++++ .../quote-added-to-cart-event.listener.ts | 7 +-- .../quote/core/facade/quote.service.ts | 27 ++++++---- .../occ-quote-action-normalizer.spec.ts | 17 +++++-- .../converters/occ-quote-action-normalizer.ts | 2 - 5 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 feature-libs/quote/core/event/quote-added-to-cart-event.listener.spec.ts diff --git a/feature-libs/quote/core/event/quote-added-to-cart-event.listener.spec.ts b/feature-libs/quote/core/event/quote-added-to-cart-event.listener.spec.ts new file mode 100644 index 00000000000..6433a8c0e61 --- /dev/null +++ b/feature-libs/quote/core/event/quote-added-to-cart-event.listener.spec.ts @@ -0,0 +1,51 @@ +import { TestBed } from '@angular/core/testing'; +import { + CartAddEntryFailEvent, + CartUiEventAddToCart, +} from '@spartacus/cart/base/root'; +import { CxEvent, EventService } from '@spartacus/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { QuoteAddedToCartEventListener } from './quote-added-to-cart-event.listener'; + +const mockEventStream$ = new BehaviorSubject({}); + +class MockEventService implements Partial { + get(): Observable { + return mockEventStream$.asObservable(); + } + dispatch() {} +} + +const mockEvent = new CartUiEventAddToCart(); +mockEvent.productCode = 'test'; +mockEvent.quantity = 3; +mockEvent.numberOfEntriesBeforeAdd = 1; +mockEvent.pickupStoreName = 'testStore'; + +const mockFailEvent = new CartAddEntryFailEvent(); +mockFailEvent.error = {}; + +describe('AddToCartDialogEventListener', () => { + let listener: QuoteAddedToCartEventListener; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + QuoteAddedToCartEventListener, + { + provide: EventService, + useClass: MockEventService, + }, + ], + }); + + listener = TestBed.inject(QuoteAddedToCartEventListener); + }); + + describe('onAddToCart', () => { + it('Should ', () => { + expect(listener).toBeDefined(); + mockEventStream$.next(mockEvent); + }); + }); +}); diff --git a/feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts b/feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts index d00dff76c9d..bcea5a4918a 100644 --- a/feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts +++ b/feature-libs/quote/core/event/quote-added-to-cart-event.listener.ts @@ -8,7 +8,7 @@ import { Injectable, OnDestroy } from '@angular/core'; import { CartUiEventAddToCart } from '@spartacus/cart/base/root'; import { EventService } from '@spartacus/core'; import { QuoteDetailsReloadQueryEvent } from '@spartacus/quote/root'; -import { LaunchDialogService } from '@spartacus/storefront'; + import { Subscription } from 'rxjs'; @Injectable({ @@ -17,10 +17,7 @@ import { Subscription } from 'rxjs'; export class QuoteAddedToCartEventListener implements OnDestroy { protected subscription = new Subscription(); - constructor( - protected eventService: EventService, - protected launchDialogService: LaunchDialogService - ) { + constructor(protected eventService: EventService) { this.onAddToCart(); } diff --git a/feature-libs/quote/core/facade/quote.service.ts b/feature-libs/quote/core/facade/quote.service.ts index 6ded67f604b..4c6a9cd99b6 100644 --- a/feature-libs/quote/core/facade/quote.service.ts +++ b/feature-libs/quote/core/facade/quote.service.ts @@ -169,6 +169,10 @@ export class QuoteService implements QuoteFacade { if (payload.quoteAction === QuoteActionType.SUBMIT) { this.quoteCartService.setQuoteCartActive(false); } + if (payload.quoteAction === QuoteActionType.EDIT) { + this.quoteCartService.setQuoteCartActive(true); + this.quoteCartService.setQuoteId(payload.quoteCode); + } }) ); }, @@ -209,20 +213,21 @@ export class QuoteService implements QuoteFacade { switchMap(([{ state }, userId]) => zip( this.quoteConnector.getQuote(userId, state.params.quoteId), + this.quoteCartService.getQuoteCartActive(), + this.quoteCartService.getQuoteId(), of(userId) ) ), - //TODO CHHI only if user explictly triggered edit for this quote - tap(([quote, userId]) => { - this.multiCartService.loadCart({ - userId: userId, - cartId: quote.cartId as string, - extraData: { - active: true, - }, - }); - this.quoteCartService.setQuoteCartActive(true); - this.quoteCartService.setQuoteId(quote.code); + tap(([quote, isActive, quoteId, userId]) => { + if (isActive && quote.code === quoteId) { + this.multiCartService.loadCart({ + userId: userId, + cartId: quote.cartId as string, + extraData: { + active: true, + }, + }); + } }), map(([quote, _]) => quote) ), diff --git a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.spec.ts b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.spec.ts index 02ec438764f..0b2e2077e73 100644 --- a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.spec.ts +++ b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.spec.ts @@ -6,7 +6,10 @@ import { QuoteActionType, QuoteState, } from '@spartacus/quote/root'; -import { createEmptyQuote } from '../../core/testing/quote-test-utils'; +import { + createEmptyQuote, + QUOTE_CODE, +} from '../../core/testing/quote-test-utils'; import { OccQuoteActionNormalizer } from './occ-quote-action-normalizer'; const SUBMIT_AND_CANCEL_UNORDERED = [ @@ -95,7 +98,8 @@ describe('OccQuoteActionNormalizer', () => { it('should return sorted list according to config', () => { const orderedActions = service['getOrderedActions']( QuoteState.BUYER_DRAFT, - SUBMIT_AND_CANCEL_UNORDERED + SUBMIT_AND_CANCEL_UNORDERED, + QUOTE_CODE ); expect(orderedActions).toEqual([ QuoteActionType.CANCEL, @@ -106,7 +110,8 @@ describe('OccQuoteActionNormalizer', () => { quoteCoreConfig.quote = undefined; const orderedActions = service['getOrderedActions']( QuoteState.BUYER_DRAFT, - SUBMIT_AND_CANCEL_UNORDERED + SUBMIT_AND_CANCEL_UNORDERED, + QUOTE_CODE ); expect(orderedActions).toEqual(SUBMIT_AND_CANCEL_UNORDERED); }); @@ -114,7 +119,8 @@ describe('OccQuoteActionNormalizer', () => { (quoteCoreConfig?.quote ?? {}).actions = undefined; const orderedActions = service['getOrderedActions']( QuoteState.BUYER_DRAFT, - SUBMIT_AND_CANCEL_UNORDERED + SUBMIT_AND_CANCEL_UNORDERED, + QUOTE_CODE ); expect(orderedActions).toEqual(SUBMIT_AND_CANCEL_UNORDERED); }); @@ -123,7 +129,8 @@ describe('OccQuoteActionNormalizer', () => { (quoteCoreConfig.quote?.actions ?? {}).actionsOrderByState = undefined; const orderedActions = service['getOrderedActions']( QuoteState.BUYER_DRAFT, - SUBMIT_AND_CANCEL_UNORDERED + SUBMIT_AND_CANCEL_UNORDERED, + QUOTE_CODE ); expect(orderedActions).toEqual(SUBMIT_AND_CANCEL_UNORDERED); }); diff --git a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts index 6e7f4bff484..02fc8a80787 100644 --- a/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts +++ b/feature-libs/quote/occ/converters/occ-quote-action-normalizer.ts @@ -74,8 +74,6 @@ export class OccQuoteActionNormalizer implements Converter { ]) .pipe(take(1)) .subscribe(([isQuoteCartActive, cartQuoteId]) => { - console.log('CHHI cart quote id: ' + cartQuoteId); - console.log('CHHI current quote id: ' + quoteId); if (isQuoteCartActive && cartQuoteId === quoteId) { const editIndex = clonedActionList.indexOf(QuoteActionType.EDIT); if (editIndex > -1) {