Skip to content

Commit

Permalink
feat: Create Order Template from Order (#1610)
Browse files Browse the repository at this point in the history
Co-authored-by: LucasHengelhaupt <l.hengelhaupt@intershop.com>
Co-authored-by: Silke <s.grueber@intershop.de>
  • Loading branch information
3 people authored Apr 8, 2024
1 parent 11495fc commit 553e05a
Show file tree
Hide file tree
Showing 25 changed files with 491 additions and 145 deletions.
4 changes: 4 additions & 0 deletions docs/guides/migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ kb_sync_latest_only

# Migrations

## From 5.1 to 5.2

The store action and method `addBasketToNewOrderTemplate` of the OrderTemplatesFacade have been renamed to `createOrderTemplateFromLineItems` and refactored slightly.

## From 5.0 to 5.1

The OrderListComponent is strictly presentational, components using it have to supply the data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FeatureToggleModule } from 'ish-core/feature-toggle.module';
import { LAZY_FEATURE_MODULE } from 'ish-core/utils/module-loader/module-loader.service';

import { LazyBasketCreateOrderTemplateComponent } from './lazy-basket-create-order-template/lazy-basket-create-order-template.component';
import { LazyOrderCreateOrderTemplateComponent } from './lazy-order-create-order-template/lazy-order-create-order-template.component';
import { LazyOrderTemplateWidgetComponent } from './lazy-order-template-widget/lazy-order-template-widget.component';
import { LazyProductAddToOrderTemplateComponent } from './lazy-product-add-to-order-template/lazy-product-add-to-order-template.component';

Expand All @@ -21,11 +22,13 @@ import { LazyProductAddToOrderTemplateComponent } from './lazy-product-add-to-or
],
declarations: [
LazyBasketCreateOrderTemplateComponent,
LazyOrderCreateOrderTemplateComponent,
LazyOrderTemplateWidgetComponent,
LazyProductAddToOrderTemplateComponent,
],
exports: [
LazyBasketCreateOrderTemplateComponent,
LazyOrderCreateOrderTemplateComponent,
LazyOrderTemplateWidgetComponent,
LazyProductAddToOrderTemplateComponent,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { Observable } from 'rxjs';
import { map, startWith, withLatestFrom } from 'rxjs/operators';

import { HttpError } from 'ish-core/models/http-error/http-error.model';
import { LineItem } from 'ish-core/models/line-item/line-item.model';
import { SelectOption } from 'ish-core/models/select-option/select-option.model';

import { OrderTemplate, OrderTemplateHeader } from '../models/order-template/order-template.model';
import {
addBasketToNewOrderTemplate,
addProductToNewOrderTemplate,
addProductToOrderTemplate,
createOrderTemplate,
Expand All @@ -19,6 +19,7 @@ import {
getSelectedOrderTemplateDetails,
getSelectedOrderTemplateOutOfStockItems,
moveItemToOrderTemplate,
orderTemplatesActions,
removeItemFromOrderTemplate,
updateOrderTemplate,
} from '../store/order-template';
Expand Down Expand Up @@ -58,8 +59,8 @@ export class OrderTemplatesFacade {
this.store.dispatch(createOrderTemplate({ orderTemplate }));
}

addBasketToNewOrderTemplate(orderTemplate: OrderTemplateHeader): void | HttpError {
this.store.dispatch(addBasketToNewOrderTemplate({ orderTemplate }));
createOrderTemplateFromLineItems(orderTemplate: OrderTemplateHeader, lineItems: LineItem[]): void | HttpError {
this.store.dispatch(orderTemplatesActions.createOrderTemplateFromLineItems({ orderTemplate, lineItems }));
}

deleteOrderTemplate(id: string): void {
Expand Down
2 changes: 2 additions & 0 deletions src/app/extensions/order-templates/order-templates.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
import { SharedModule } from 'ish-shared/shared.module';

import { BasketCreateOrderTemplateComponent } from './shared/basket-create-order-template/basket-create-order-template.component';
import { OrderCreateOrderTemplateComponent } from './shared/order-create-order-template/order-create-order-template.component';
import { OrderTemplatePreferencesDialogComponent } from './shared/order-template-preferences-dialog/order-template-preferences-dialog.component';
import { OrderTemplateWidgetComponent } from './shared/order-template-widget/order-template-widget.component';
import { ProductAddToOrderTemplateComponent } from './shared/product-add-to-order-template/product-add-to-order-template.component';
Expand All @@ -13,6 +14,7 @@ import { SelectOrderTemplateModalComponent } from './shared/select-order-templat
imports: [SharedModule],
declarations: [
BasketCreateOrderTemplateComponent,
OrderCreateOrderTemplateComponent,
OrderTemplatePreferencesDialogComponent,
OrderTemplateWidgetComponent,
ProductAddToOrderTemplateComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
<button
type="submit"
name="addProduct"
[ngClass]="cssClass"
(click)="openModal(modal)"
data-testing-id="addBasketToOrderTemplateButton"
>
<button type="button" [ngClass]="cssClass" (click)="openModal(modal)" data-testing-id="addBasketToOrderTemplateButton">
{{ 'order_template.create.heading' | translate }}
</button>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { MockComponent } from 'ng-mocks';
import { instance, mock } from 'ts-mockito';
import { anything, instance, mock, verify } from 'ts-mockito';

import { AccountFacade } from 'ish-core/facades/account.facade';

import { OrderTemplatesFacade } from '../../facades/order-templates.facade';
import { OrderTemplate } from '../../models/order-template/order-template.model';
import { OrderTemplatePreferencesDialogComponent } from '../order-template-preferences-dialog/order-template-preferences-dialog.component';

import { BasketCreateOrderTemplateComponent } from './basket-create-order-template.component';
Expand All @@ -15,13 +16,17 @@ describe('Basket Create Order Template Component', () => {
let fixture: ComponentFixture<BasketCreateOrderTemplateComponent>;
let element: HTMLElement;

let orderTemplatesFacadeMock: OrderTemplatesFacade;

beforeEach(async () => {
orderTemplatesFacadeMock = mock(OrderTemplatesFacade);

await TestBed.configureTestingModule({
declarations: [BasketCreateOrderTemplateComponent, MockComponent(OrderTemplatePreferencesDialogComponent)],
imports: [TranslateModule.forRoot()],
providers: [
{ provide: AccountFacade, useFactory: () => instance(mock(AccountFacade)) },
{ provide: OrderTemplatesFacade, useFactory: () => instance(mock(OrderTemplatesFacade)) },
{ provide: OrderTemplatesFacade, useFactory: () => instance(orderTemplatesFacadeMock) },
],
}).compileComponents();
});
Expand All @@ -37,4 +42,16 @@ describe('Basket Create Order Template Component', () => {
expect(element).toBeTruthy();
expect(() => fixture.detectChanges()).not.toThrow();
});

it('should render the create order-template from basket button', () => {
fixture.detectChanges();

expect(element.querySelector('button[data-testing-id=addBasketToOrderTemplateButton]')).toBeTruthy();
});

it('should trigger createOrderTemplatesFromLineItems when createOrderTemplates is called', () => {
component.createOrderTemplate({ id: 'orderTemplateId' } as OrderTemplate);

verify(orderTemplatesFacadeMock.createOrderTemplateFromLineItems(anything(), anything())).once();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ export class BasketCreateOrderTemplateComponent {
}

createOrderTemplate(orderTemplate: OrderTemplate) {
this.orderTemplatesFacade.addBasketToNewOrderTemplate(orderTemplate);
this.orderTemplatesFacade.createOrderTemplateFromLineItems(orderTemplate, this.products);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<button
type="button"
class="btn btn-secondary btn-block"
[ngClass]="cssClass"
(click)="openModal(modal)"
[disabled]="displaySpinner()"
data-testing-id="addOrderToOrderTemplateButton"
>
<ng-container *ngIf="displaySpinner() !== true; else spinning">
{{ 'order_template.create.heading' | translate }}
</ng-container>
<!-- spinning animation after clicking button -->
<ng-template #spinning>
<fa-icon [icon]="['fas', 'spinner']" [spin]="true" ngClass="pr-3" />
<span>{{ 'common.button.spinning.label' | translate }}</span></ng-template
>&nbsp;
</button>

<ish-order-template-preferences-dialog
#modal
modalTitle="account.order_template.new_from_order.heading"
(submitOrderTemplate)="createOrderTemplate($event)"
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { MockComponent } from 'ng-mocks';
import { of } from 'rxjs';
import { anything, instance, mock, verify, when } from 'ts-mockito';

import { OrderTemplatesFacade } from '../../facades/order-templates.facade';
import { OrderTemplate } from '../../models/order-template/order-template.model';
import { OrderTemplatePreferencesDialogComponent } from '../order-template-preferences-dialog/order-template-preferences-dialog.component';

import { OrderCreateOrderTemplateComponent } from './order-create-order-template.component';

describe('Order Create Order Template Component', () => {
let component: OrderCreateOrderTemplateComponent;
let fixture: ComponentFixture<OrderCreateOrderTemplateComponent>;
let element: HTMLElement;

let orderTemplatesFacadeMock: OrderTemplatesFacade;

beforeEach(async () => {
orderTemplatesFacadeMock = mock(OrderTemplatesFacade);

when(orderTemplatesFacadeMock.orderTemplateLoading$).thenReturn(of(false));

await TestBed.configureTestingModule({
declarations: [MockComponent(OrderTemplatePreferencesDialogComponent), OrderCreateOrderTemplateComponent],
imports: [TranslateModule.forRoot()],
providers: [{ provide: OrderTemplatesFacade, useFactory: () => instance(orderTemplatesFacadeMock) }],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(OrderCreateOrderTemplateComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
});

it('should be created', () => {
expect(component).toBeTruthy();
expect(element).toBeTruthy();
expect(() => fixture.detectChanges()).not.toThrow();
});

it('should render the create order-template from order button', () => {
fixture.detectChanges();

expect(element.querySelector('button[data-testing-id="addOrderToOrderTemplateButton"]')).toBeTruthy();
});

it('should trigger createOrderTemplatesFromLineItems when createOrderTemplates is called', () => {
component.createOrderTemplate({ id: 'orderTemplateId' } as OrderTemplate);

verify(orderTemplatesFacadeMock.createOrderTemplateFromLineItems(anything(), anything())).once();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ChangeDetectionStrategy, Component, Input, Signal } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';

import { LineItemView } from 'ish-core/models/line-item/line-item.model';
import { GenerateLazyComponent } from 'ish-core/utils/module-loader/generate-lazy-component.decorator';

import { OrderTemplatesFacade } from '../../facades/order-templates.facade';
import { OrderTemplate } from '../../models/order-template/order-template.model';
import { OrderTemplatePreferencesDialogComponent } from '../order-template-preferences-dialog/order-template-preferences-dialog.component';

@Component({
selector: 'ish-order-create-order-template',
templateUrl: './order-create-order-template.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
/**
* The Create Order Template from Order displays a button which adds the current order to to a new order template.
*/

@GenerateLazyComponent()
export class OrderCreateOrderTemplateComponent {
@Input({ required: true }) lineItems: LineItemView[];
@Input() cssClass: string;

displaySpinner: Signal<boolean>;

constructor(private orderTemplatesFacade: OrderTemplatesFacade) {
this.displaySpinner = toSignal(this.orderTemplatesFacade.orderTemplateLoading$, { initialValue: false });
}

openModal(modal: OrderTemplatePreferencesDialogComponent) {
modal.show();
}

createOrderTemplate(orderTemplate: OrderTemplate) {
this.orderTemplatesFacade.createOrderTemplateFromLineItems(orderTemplate, this.lineItems);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<ng-template #modal let-addModal>
<div class="modal-header">
<h2 class="modal-title">{{ modalHeader | translate }}</h2>
<h2 class="modal-title">{{ this.modalTitle || modalHeader | translate }}</h2>
<button type="button" class="close" [title]="'dialog.close.text' | translate" (click)="hide()">
<span aria-hidden="true">&times;</span>
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createAction } from '@ngrx/store';
import { createAction, createActionGroup } from '@ngrx/store';

import { LineItem } from 'ish-core/models/line-item/line-item.model';
import { httpError, payload } from 'ish-core/utils/ngrx-creators';

import { OrderTemplate, OrderTemplateHeader } from '../../models/order-template/order-template.model';
Expand Down Expand Up @@ -94,17 +95,17 @@ export const selectOrderTemplate = createAction(
payload<{ id: string }>()
);

export const addBasketToNewOrderTemplate = createAction(
'[Order Templates] Add basket to New Order Template]',
payload<{ orderTemplate: OrderTemplateHeader }>()
);

export const addBasketToNewOrderTemplateFail = createAction(
'[Order Templates API] Add basket to New Order Template Fail]',
httpError()
);

export const addBasketToNewOrderTemplateSuccess = createAction(
'[Order Templates API] Add basket to New Order Template Success]',
payload<{ orderTemplate: OrderTemplate }>()
);
export const orderTemplatesActions = createActionGroup({
source: 'Order Templates',
events: {
'Create Order Template from Line Items': payload<{ orderTemplate: OrderTemplateHeader; lineItems: LineItem[] }>(),
},
});

export const orderTemplatesApiActions = createActionGroup({
source: 'Order Templates API',
events: {
'Create Order Template from Line Items Success': payload<{ orderTemplate: OrderTemplate }>(),
'Create Order Template from Line Items Fail': httpError<{}>(),
},
});
Loading

0 comments on commit 553e05a

Please sign in to comment.