Merged PR 1815: Angular Update V18

Related work items: #4830, #4834
This commit is contained in:
Lorenz Hilpert
2024-10-22 09:23:23 +00:00
committed by Nino Righi
parent 301f5878c2
commit 8ae990bcde
1026 changed files with 397921 additions and 12034 deletions

5
.gitignore vendored
View File

@@ -5,6 +5,8 @@
/tmp
/out-tsc
/
# dependencies
/node_modules
@@ -47,4 +49,5 @@ testem.log
.DS_Store
Thumbs.db
libs/swagger/src/lib/*
libs/swagger/src/lib/*
*storybook.log

View File

@@ -24,6 +24,6 @@ ARG BuildUniqueID
LABEL build.uniqueid="${BuildUniqueID:-1}"
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -q -O /tmp/chrome.deb && apt update && apt install -y /tmp/chrome.deb
# ignore exitcode, sonst gibts keinen container
RUN npm test || true
RUN npm run ci || true
ENTRYPOINT [ "/bin/sleep", "60000" ]

View File

@@ -125,6 +125,36 @@
],
"scripts": []
}
},
"storybook": {
"builder": "@storybook/angular:start-storybook",
"options": {
"configDir": "apps/isa-app/.storybook",
"browserTarget": "isa-app:build",
"compodoc": true,
"compodocArgs": [
"-e",
"json",
"-d",
"apps/isa-app"
],
"port": 6006
}
},
"build-storybook": {
"builder": "@storybook/angular:build-storybook",
"options": {
"configDir": "apps/isa-app/.storybook",
"browserTarget": "isa-app:build",
"compodoc": true,
"compodocArgs": [
"-e",
"json",
"-d",
"apps/isa-app"
],
"outputDir": "storybook-static"
}
}
}
}

View File

@@ -0,0 +1,17 @@
import type { StorybookConfig } from '@storybook/angular';
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-onboarding',
'@storybook/addon-links',
'@storybook/addon-essentials',
'@chromatic-com/storybook',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/angular',
options: {},
},
};
export default config;

View File

@@ -0,0 +1,17 @@
import type { Preview } from '@storybook/angular';
import { setCompodocJson } from '@storybook/addon-docs/angular';
import docJson from '../documentation.json';
setCompodocJson(docJson);
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};
export default preview;

View File

@@ -0,0 +1,10 @@
// This tsconfig is used by Compodoc to generate the documentation for the project.
// If Compodoc is not used, this file can be deleted.
{
"extends": "./tsconfig.json",
// Exclude all files that are not needed for documentation generation.
"exclude": ["../src/test.ts", "../src/**/*.spec.ts", "../src/**/*.stories.ts"],
// Please make sure to include all files from which Compodoc should generate documentation.
"include": ["../src/**/*"],
"files": ["./typings.d.ts"]
}

View File

@@ -0,0 +1,11 @@
{
"extends": "../tsconfig.app.json",
"compilerOptions": {
"types": ["node"],
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
},
"exclude": ["../src/test.ts", "../src/**/*.spec.ts"],
"include": ["../src/**/*.stories.*", "./preview.ts", "../src/polyfills.ts"],
"files": ["./typings.d.ts"]
}

4
apps/isa-app/.storybook/typings.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
declare module '*.md' {
const content: string;
export default content;
}

373381
apps/isa-app/documentation.json Normal file
View File

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
import { Injectable, isDevMode } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { EnvironmentService } from '@core/environment';
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
import { Observable } from 'rxjs';
@@ -8,10 +8,7 @@ import { ScanAdapter } from './scan-adapter';
export class DevScanAdapter implements ScanAdapter {
readonly name = 'Dev';
constructor(
private _modal: UiModalService,
private _environmentService: EnvironmentService,
) {}
private _modal = inject(UiModalService);
async init(): Promise<boolean> {
return Promise.resolve(false);

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy } from '@angular/core';
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy, inject } from '@angular/core';
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
import { Barcode, BarcodePicker, ScanResult, ScanSettings } from 'scandit-sdk';
@@ -15,12 +15,11 @@ export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
private _onClose?: () => void;
private _modal = inject(UiModalService);
@ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;
constructor(
private _zone: NgZone,
private _modal: UiModalService,
) {}
constructor(private _zone: NgZone) {}
ngAfterViewInit(): void {
this.createBarcodePicker()

View File

@@ -1,4 +1,4 @@
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { APP_INITIALIZER, ErrorHandler, Injector, LOCALE_ID, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@@ -123,10 +123,10 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
@NgModule({
declarations: [AppComponent, MainComponent],
bootstrap: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
ShellModule.forRoot(),
AppRoutingModule,
AppSwaggerModule,
@@ -182,7 +182,7 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
useClass: IsaErrorHandler,
},
{ provide: LOCALE_ID, useValue: 'de-DE' },
provideHttpClient(withInterceptorsFromDi()),
],
bootstrap: [AppComponent],
})
export class AppModule {}

View File

@@ -1,66 +1,66 @@
import { HttpErrorInterceptor } from './http-error.interceptor';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
import { UiMessageModalComponent, UiModalResult, UiModalService } from '@ui/modal';
import { of, Subject, throwError } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { AuthService } from '@core/auth';
// import { HttpErrorInterceptor } from './http-error.interceptor';
// import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
// import { UiMessageModalComponent, UiModalResult, UiModalService } from '@ui/modal';
// import { of, Subject, throwError } from 'rxjs';
// import { HttpErrorResponse } from '@angular/common/http';
// import { AuthService } from '@core/auth';
describe('HttpErrorInterceptor', () => {
let spectator: SpectatorService<HttpErrorInterceptor>;
let modalMock: jasmine.SpyObj<UiModalService>;
let httpErrorInterceptor: HttpErrorInterceptor;
// describe('HttpErrorInterceptor', () => {
// let spectator: SpectatorService<HttpErrorInterceptor>;
// let modalMock: jasmine.SpyObj<UiModalService>;
// let httpErrorInterceptor: HttpErrorInterceptor;
const createService = createServiceFactory({
service: HttpErrorInterceptor,
mocks: [UiModalService, AuthService],
});
// const createService = createServiceFactory({
// service: HttpErrorInterceptor,
// mocks: [UiModalService, AuthService],
// });
beforeEach(() => {
spectator = createService();
httpErrorInterceptor = spectator.service;
modalMock = spectator.inject(UiModalService);
// beforeEach(() => {
// spectator = createService();
// httpErrorInterceptor = spectator.service;
// modalMock = spectator.inject(UiModalService);
modalMock.open.and.returnValue({
afterClosed$: of({} as UiModalResult<any>),
} as any);
});
// modalMock.open.and.returnValue({
// afterClosed$: of({} as UiModalResult<any>),
// } as any);
// });
it('should be created', () => {
expect(httpErrorInterceptor).toBeTruthy();
});
// it('should be created', () => {
// expect(httpErrorInterceptor).toBeTruthy();
// });
describe('intercept', () => {
it('should catch the error and call handleError', (done) => {
const error = new HttpErrorResponse({
status: 0,
statusText: '',
url: '',
});
// describe('intercept', () => {
// it('should catch the error and call handleError', (done) => {
// const error = new HttpErrorResponse({
// status: 0,
// statusText: '',
// url: '',
// });
const handleErrorSpy = spyOn(httpErrorInterceptor, 'handleError').and.callThrough();
httpErrorInterceptor.intercept(null, { handle: () => throwError(error) }).subscribe({
error: () => {
expect(handleErrorSpy).toHaveBeenCalledWith(error);
done();
},
});
});
});
// const handleErrorSpy = spyOn(httpErrorInterceptor, 'handleError').and.callThrough();
// httpErrorInterceptor.intercept(null, { handle: () => throwError(error) }).subscribe({
// error: () => {
// expect(handleErrorSpy).toHaveBeenCalledWith(error);
// done();
// },
// });
// });
// });
describe('handleError', () => {
it('should call modal.open with offline message if status is 0', () => {
const error = {
error: {
message: 'test',
},
status: 0,
};
httpErrorInterceptor.handleError(error as any);
expect(modalMock.open).toHaveBeenCalledWith({
content: UiMessageModalComponent,
title: 'Sie sind offline, keine Verbindung zum Netzwerk',
data: { message: 'Bereits geladene Inhalte werden angezeigt. Interaktionen sind aktuell nicht möglich.' },
});
});
});
});
// describe('handleError', () => {
// it('should call modal.open with offline message if status is 0', () => {
// const error = {
// error: {
// message: 'test',
// },
// status: 0,
// };
// httpErrorInterceptor.handleError(error as any);
// expect(modalMock.open).toHaveBeenCalledWith({
// content: UiMessageModalComponent,
// title: 'Sie sind offline, keine Verbindung zum Netzwerk',
// data: { message: 'Bereits geladene Inhalte werden angezeigt. Interaktionen sind aktuell nicht möglich.' },
// });
// });
// });
// });

View File

@@ -1,4 +1,4 @@
import { Directive, HostListener, Input } from '@angular/core';
import { Directive, HostListener, inject, Input } from '@angular/core';
import { ProductCatalogNavigationService } from '@shared/services/navigation';
@Directive({
@@ -8,7 +8,7 @@ import { ProductCatalogNavigationService } from '@shared/services/navigation';
export class NavigateOnClickDirective {
@Input('productImageNavigation') ean: string;
constructor(private readonly _productCatalogNavigation: ProductCatalogNavigationService) {}
private readonly _productCatalogNavigation = inject(ProductCatalogNavigationService);
@HostListener('click', ['$event'])
async onClick(event: MouseEvent) {

View File

@@ -1 +0,0 @@
describe('Breadcrumb Actions', () => {});

View File

@@ -1,36 +1,36 @@
// unit test JsonConfigLoader
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
import { CORE_JSON_CONFIG_LOADER_URL } from '../tokens';
import { JsonConfigLoader } from './json.config-loader';
// // unit test JsonConfigLoader
// import { HttpTestingController } from '@angular/common/http/testing';
// import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
// import { CORE_JSON_CONFIG_LOADER_URL } from '../tokens';
// import { JsonConfigLoader } from './json.config-loader';
describe('JsonConfigLoader', () => {
let spectator: SpectatorService<JsonConfigLoader>;
const createService = createServiceFactory({
imports: [HttpClientTestingModule],
service: JsonConfigLoader,
mocks: [],
providers: [{ provide: CORE_JSON_CONFIG_LOADER_URL, useValue: '/assets/config.json' }],
});
let httpTestingController: HttpTestingController;
// describe('JsonConfigLoader', () => {
// let spectator: SpectatorService<JsonConfigLoader>;
// const createService = createServiceFactory({
// imports: [HttpClientTestingModule],
// service: JsonConfigLoader,
// mocks: [],
// providers: [{ provide: CORE_JSON_CONFIG_LOADER_URL, useValue: '/assets/config.json' }],
// });
// let httpTestingController: HttpTestingController;
beforeEach(() => {
spectator = createService();
httpTestingController = spectator.inject(HttpTestingController);
});
// beforeEach(() => {
// spectator = createService();
// httpTestingController = spectator.inject(HttpTestingController);
// });
it('should create', () => {
expect(spectator.service).toBeTruthy();
});
// it('should create', () => {
// expect(spectator.service).toBeTruthy();
// });
describe('load', () => {
it('should call the provided url', async () => {
const reqPromise = spectator.service.load();
const req = httpTestingController.expectOne('/assets/config.json');
req.flush({ unit: 'test' });
const result = await reqPromise;
httpTestingController.verify();
expect(result).toEqual({ unit: 'test' });
});
});
});
// describe('load', () => {
// it('should call the provided url', async () => {
// const reqPromise = spectator.service.load();
// const req = httpTestingController.expectOne('/assets/config.json');
// req.flush({ unit: 'test' });
// const result = await reqPromise;
// httpTestingController.verify();
// expect(result).toEqual({ unit: 'test' });
// });
// });
// });

View File

@@ -1,16 +1,16 @@
import { TestBed } from '@angular/core/testing';
// import { TestBed } from '@angular/core/testing';
import { DomainAvailabilityService } from './availability.service';
// import { DomainAvailabilityService } from './availability.service';
describe('AvailabilityService', () => {
let service: DomainAvailabilityService;
// describe('AvailabilityService', () => {
// let service: DomainAvailabilityService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DomainAvailabilityService);
});
// beforeEach(() => {
// TestBed.configureTestingModule({});
// service = TestBed.inject(DomainAvailabilityService);
// });
it('should be created', () => {
expect(service).toBeTruthy();
});
});
// it('should be created', () => {
// expect(service).toBeTruthy();
// });
// });

View File

@@ -36,7 +36,7 @@ export class DomainCatalogService {
search({ queryToken }: { queryToken: QueryTokenDTO }) {
return this.searchService
.SearchSearch({
queryToken,
...queryToken,
stockId: null,
})
.pipe(share());
@@ -55,54 +55,32 @@ export class DomainCatalogService {
getDetailsById({ id }: { id: number }) {
return this.searchService.SearchDetail({
id,
stockId: null,
});
}
getDetailsByEan({ ean }: { ean: string }) {
return this.searchService.SearchDetailByEAN({
ean,
stockId: null,
});
return this.searchService.SearchDetailByEAN(ean);
}
searchByIds({ ids }: { ids: number[] }) {
return this.searchService.SearchById({
ids,
stockId: null,
});
return this.searchService.SearchById(ids);
}
searchByEans({ eans }: { eans: string[] }) {
return this.searchService.SearchByEAN({
stockId: null,
branchNumber: null,
eans,
});
return this.searchService.SearchByEAN(eans);
}
searchTop({ queryToken }: { queryToken: QueryTokenDTO }) {
return this.searchService.SearchTop({
stockId: null,
queryToken,
});
return this.searchService.SearchTop(queryToken);
}
searchComplete({ queryToken }: { queryToken: AutocompleteTokenDTO }) {
return this.searchService.SearchAutocomplete({
stockId: null,
queryToken,
});
return this.searchService.SearchAutocomplete(queryToken);
}
@memorize()
getPromotionPoints({ items }: { items: { id: number; quantity: number; price?: number }[] }) {
return this.promotionService
.PromotionLesepunkte({
items,
stockId: null,
})
.pipe(shareReplay());
return this.promotionService.PromotionLesepunkte(items).pipe(shareReplay());
}
@memorize()

View File

@@ -1,5 +1,5 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { ActionHandler, CommandService } from '@core/command';
import { ReorderModalComponent, ReorderResult } from '@modal/reorder';
import { AvailabilityDTO2, OrderItemListItemDTO } from '@swagger/oms';
@@ -11,11 +11,11 @@ import { OrderItemsContext } from './order-items.context';
@Injectable()
export class OrderAtSupplierActionHandler extends ActionHandler<OrderItemsContext> {
constructor(
private _command: CommandService,
private _domainOmsService: DomainOmsService,
private _uiModal: UiModalService,
) {
private _command = inject(CommandService);
private _domainOmsService = inject(DomainOmsService);
private _uiModal = inject(UiModalService);
constructor() {
super('ORDER_AT_SUPPLIER');
}

View File

@@ -1,20 +1,18 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { ActionHandler } from '@core/command';
import { DomainPrinterService, Printer } from '@domain/printer';
import { PrintModalComponent, PrintModalData } from '@modal/printer';
import { UiModalService } from '@ui/modal';
import { NativeContainerService } from '@external/native-container';
import { OrderItemsContext } from './order-items.context';
import { EnvironmentService } from '@core/environment';
@Injectable()
export class PrintCompartmentLabelActionHandler extends ActionHandler<OrderItemsContext> {
constructor(
private uiModal: UiModalService,
private domainPrinterService: DomainPrinterService,
private nativeContainerService: NativeContainerService,
private _environmentSerivce: EnvironmentService,
) {
private uiModal = inject(UiModalService);
private domainPrinterService = inject(DomainPrinterService);
private _environmentSerivce = inject(EnvironmentService);
constructor() {
super('PRINT_COMPARTMENTLABEL');
}
printCompartmentLabelHelper(printer: string, orderItemSubsetIds: number[]) {

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { ActionHandler } from '@core/command';
import { OrderItemsContext } from './order-items.context';
import { DomainPrinterService } from '@domain/printer';
@@ -8,10 +8,10 @@ import { PrintModalComponent } from '@modal/printer';
@Injectable()
export class PrintPriceDiffQrCodeLabelActionHandler extends ActionHandler<OrderItemsContext> {
constructor(
private uiModal: UiModalService,
private domainPrinterService: DomainPrinterService,
) {
private uiModal = inject(UiModalService);
private domainPrinterService = inject(DomainPrinterService);
constructor() {
super('PRINT_PRICEDIFFQRCODELABEL');
}

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { ActionHandler } from '@core/command';
import { OrderItemsContext } from './order-items.context';
import { DomainPrinterService, Printer } from '@domain/printer';
@@ -11,12 +11,12 @@ import { EnvironmentService } from '@core/environment';
@Injectable()
export class PrintShippingNoteActionHandler extends ActionHandler<OrderItemsContext> {
constructor(
private uiModal: UiModalService,
private domainPrinterService: DomainPrinterService,
private nativeContainerService: NativeContainerService,
private _environmentSerivce: EnvironmentService,
) {
private uiModal = inject(UiModalService);
private domainPrinterService = inject(DomainPrinterService);
private nativeContainerService = inject(NativeContainerService);
private _environmentSerivce = inject(EnvironmentService);
constructor() {
super('PRINT_SHIPPINGNOTE');
}

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { ActionHandler } from '@core/command';
import { OrderItemsContext } from './order-items.context';
import { OMSPrintService } from '@swagger/print';
@@ -9,11 +9,11 @@ import { groupBy } from '@ui/common';
@Injectable()
export class PrintSmallamountinvoiceActionHandler extends ActionHandler<OrderItemsContext> {
constructor(
private uiModal: UiModalService,
private omsPrintService: OMSPrintService,
private nativeContainerService: NativeContainerService,
) {
private uiModal = inject(UiModalService);
private omsPrintService = inject(OMSPrintService);
private nativeContainerService = inject(NativeContainerService);
constructor() {
super('PRINT_SMALLAMOUNTINVOICE');
}

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { ActionHandler, CommandService } from '@core/command';
import { OrderItemsContext } from './order-items.context';
import { UiModalService } from '@ui/modal';
@@ -9,12 +9,12 @@ import { ToasterService } from '@shared/shell';
@Injectable()
export class ReOrderActionHandler extends ActionHandler<OrderItemsContext> {
constructor(
private _command: CommandService,
private _domainCheckoutService: DomainCheckoutService,
private _uiModal: UiModalService,
private _toastService: ToasterService,
) {
private _command = inject(CommandService);
private _domainCheckoutService = inject(DomainCheckoutService);
private _uiModal = inject(UiModalService);
private _toastService = inject(ToasterService);
constructor() {
super('REORDER');
}

View File

@@ -274,12 +274,9 @@ export class DomainRemissionService {
switchMap((stock) =>
this._search
.SearchSearch({
stockId: null,
queryToken: {
stockId: stock.id,
input: { qs: ean },
doNotTrack: true,
},
stockId: stock.id,
input: { qs: ean },
doNotTrack: true,
})
.pipe(
catchError((err) => of({ hits: 0, result: [] })),

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { CrmCustomerService } from '@domain/crm';
import { AddressDTO } from '@swagger/crm';
import { UiModalService } from '@ui/modal';
@@ -7,10 +7,9 @@ import { AddressSelectionModalComponent } from './address-selection-modal.compon
@Injectable({ providedIn: 'root' })
export class AddressSelectionModalService {
constructor(
private customerService: CrmCustomerService,
private modal: UiModalService,
) {}
private modal = inject(UiModalService);
constructor(private customerService: CrmCustomerService) {}
async validateAddress(address: AddressDTO): Promise<AddressDTO> {
if (address.street && address.streetNumber && address.zipCode && address.city && address.country) {

View File

@@ -1,12 +1,12 @@
import { UiModalRef, UiModalService } from '@ui/modal';
import { KulturpassOrderModalData } from './kulturpass-order-modal.data';
import { KulturpassOrderModalComponent } from './kulturpass-order-modal.component';
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { DisplayOrderDTO } from '@swagger/oms';
@Injectable({ providedIn: 'root' })
export class KulturpassOrderModalService {
constructor(private modal: UiModalService) {}
private modal = inject(UiModalService);
open(data: KulturpassOrderModalData): UiModalRef<[DisplayOrderDTO, string], KulturpassOrderModalData> {
return this.modal.open<[DisplayOrderDTO, string], KulturpassOrderModalData>({

View File

@@ -1,5 +1,7 @@
import { Injectable } from '@angular/core';
import { ComponentStore, OnStoreInit, tapResponse } from '@ngrx/component-store';
import { inject, Injectable } from '@angular/core';
import { ComponentStore, OnStoreInit } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import {
AddToShoppingCartDTO,
AvailabilityDTO,
@@ -39,6 +41,12 @@ export interface KulturpassOrderModalState {
@Injectable()
export class KulturpassOrderModalStore extends ComponentStore<KulturpassOrderModalState> implements OnStoreInit {
private _checkoutService = inject(DomainCheckoutService);
private _branchService = inject(BranchService);
private _authService = inject(AuthService);
private _availabilityService = inject(DomainAvailabilityService);
private _modal = inject(UiModalService);
readonly processId = Date.now();
get orderItemListItem() {
@@ -61,13 +69,7 @@ export class KulturpassOrderModalStore extends ComponentStore<KulturpassOrderMod
return this.get((s) => s.fetchShoppingCart);
}
constructor(
private _checkoutService: DomainCheckoutService,
private _branchService: BranchService,
private _authService: AuthService,
private _availabilityService: DomainAvailabilityService,
private _modal: UiModalService,
) {
constructor() {
super({
availabilities: {},
});

View File

@@ -1,15 +1,16 @@
import { Injectable } from '@angular/core';
import { ComponentStore, OnStoreInit, tapResponse } from '@ngrx/component-store';
import { inject, Injectable } from '@angular/core';
import { ComponentStore, OnStoreInit } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ItemDTO, ResponseArgsOfItemDTO } from '@swagger/cat';
import { switchMap, withLatestFrom } from 'rxjs/operators';
import { Observable, Subject, asapScheduler } from 'rxjs';
import { Subject, asapScheduler } from 'rxjs';
import { DomainAvailabilityService } from '@domain/availability';
import { DomainCatalogService } from '@domain/catalog';
import { AddToShoppingCartDTO, AvailabilityDTO, BranchDTO } from '@swagger/checkout';
import { AddToShoppingCartDTO, BranchDTO } from '@swagger/checkout';
import { tap } from 'rxjs/operators';
import { UiModalService } from '@ui/modal';
import { KulturpassOrderModalStore } from '../kulturpass-order-modal.store';
import { getCatalogProductNumber } from '../catalog-product-number';
export interface KulturpassOrderSearchboxState {
query: string;
@@ -19,6 +20,11 @@ export interface KulturpassOrderSearchboxState {
@Injectable()
export class KulturpassOrderSearchboxStore extends ComponentStore<KulturpassOrderSearchboxState> implements OnStoreInit {
private _parentStore = inject(KulturpassOrderModalStore);
private _catalogService = inject(DomainCatalogService);
private _availabilityService = inject(DomainAvailabilityService);
private _modal = inject(UiModalService);
get query() {
return this.get((s) => s.query);
}
@@ -35,12 +41,7 @@ export class KulturpassOrderSearchboxStore extends ComponentStore<KulturpassOrde
hint$ = new Subject<string>();
constructor(
private _parentStore: KulturpassOrderModalStore,
private _catalogService: DomainCatalogService,
private _availabilityService: DomainAvailabilityService,
private _modal: UiModalService,
) {
constructor() {
super({ query: '', fetching: false });
}

View File

@@ -1,4 +1,4 @@
export * from './message-modal.action';
export * from './message-modal.component';
export * from './message-modal.data';
export * from './message-modal.service';
export * from './message-modal.injector';

View File

@@ -0,0 +1,11 @@
import { inject } from '@angular/core';
import { UiModalRef, UiModalService } from '@ui/modal';
import { MessageModalData } from './message-modal.data';
import { MessageModalComponent } from './message-modal.component';
export const injectOpenMessageModal = () => {
const modalService = inject(UiModalService);
return (data: MessageModalData): UiModalRef<void, MessageModalComponent> =>
modalService.open({ title: data.title, content: MessageModalComponent, data });
};

View File

@@ -1,17 +0,0 @@
import { Injectable } from '@angular/core';
import { UiModalRef, UiModalService } from '@ui/modal';
import { MessageModalData } from './message-modal.data';
import { MessageModalComponent } from './message-modal.component';
@Injectable({ providedIn: 'root' })
export class MessageModalService {
constructor(private _modal: UiModalService) {}
open(data: MessageModalData): UiModalRef<void, MessageModalComponent> {
return this._modal.open({
title: data.title,
content: MessageModalComponent,
data,
});
}
}

View File

@@ -1,3 +1,2 @@
export * from './modal-printer.component';
export * from './modal-printer.data';
export * from './modal-printer.module';

View File

@@ -6,12 +6,19 @@ import { isResponseArgs } from '@utils/object';
import { Observable, Subscription } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { PrintModalData } from './modal-printer.data';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { UiIconModule } from '@ui/icon';
import { UiSelectModule } from '@ui/select';
import { UiSpinnerModule } from '@ui/spinner';
@Component({
selector: 'modal-print-cart',
templateUrl: 'modal-printer.component.html',
styleUrls: ['modal-printer.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [CommonModule, FormsModule, UiIconModule, UiSelectModule, UiSpinnerModule],
})
export class PrintModalComponent implements OnInit, OnDestroy {
selectedPrinterKey: string;

View File

@@ -1,15 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { UiIconModule } from '@ui/icon';
import { UiModalModule } from '@ui/modal';
import { UiSelectModule } from '@ui/select';
import { UiSpinnerModule } from '@ui/spinner';
import { PrintModalComponent } from './modal-printer.component';
@NgModule({
declarations: [PrintModalComponent],
imports: [CommonModule, FormsModule, UiModalModule, UiIconModule, UiSelectModule, UiSpinnerModule],
exports: [PrintModalComponent],
})
export class ModalPrinterModule {}

View File

@@ -1,5 +1,4 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ApplicationService } from '@core/application';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { DomainAvailabilityService } from '@domain/availability';
import { DomainOmsService } from '@domain/oms';
import { ComponentStore } from '@ngrx/component-store';
@@ -25,6 +24,9 @@ interface GoodsInListReorderModalState {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ReorderModalComponent extends ComponentStore<GoodsInListReorderModalState> {
private domainAvailabilityService = inject(DomainAvailabilityService);
private _omsService = inject(DomainOmsService);
readonly orderItem$ = this.select((s) => s.orderItem);
get orderItem() {
return this.get((s) => s.orderItem);
@@ -138,12 +140,7 @@ export class ReorderModalComponent extends ComponentStore<GoodsInListReorderModa
takeAwayAvailabilityError: boolean;
selectedReason: string;
constructor(
public modalRef: UiModalRef<ReorderResult, { item: OrderItemListItemDTO; showReasons: boolean }>,
private domainAvailabilityService: DomainAvailabilityService,
private _omsService: DomainOmsService,
private _applicationService: ApplicationService,
) {
constructor(public modalRef: UiModalRef<ReorderResult, { item: OrderItemListItemDTO; showReasons: boolean }>) {
super({
orderItem: modalRef.data?.item,
checkedAvailability: undefined,

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { DomainPackageInspectionService } from '@domain/package-inspection';
import { PackageDTO2 } from '@swagger/wws';
import { UiModalRef, UiModalService } from '@ui/modal';
@@ -8,10 +8,8 @@ import { WrongDestinationModalData } from './wrong-destination-modal.data';
@Injectable({ providedIn: 'root' })
export class WrongDestinationModalService {
constructor(
private _packageInspectionService: DomainPackageInspectionService,
private _modal: UiModalService,
) {}
private _packageInspectionService = inject(DomainPackageInspectionService);
private _modal = inject(UiModalService);
fetchPackages(): Observable<PackageDTO2[]> {
return this._packageInspectionService.queryPackages({

View File

@@ -30,7 +30,7 @@
</div>
<div class="items scroll-bar">
@for (item of items; track item.id; let first = $first) {
@for (item of items; track item.uId; let first = $first) {
@defer (on viewport) {
<page-price-update-item [item]="item" [selected]="isSelected(item)" [class.mt-px-10]="!first"></page-price-update-item>
} @placeholder {

View File

@@ -1,5 +1,5 @@
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { ChangeDetectionStrategy, Component, Input, ViewChild } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input, OnChanges, ViewChild } from '@angular/core';
import { ProductListItemDTO } from '@swagger/wws';
import { map } from 'rxjs/operators';
import { PriceUpdateComponentStore } from '../price-update.component.store';

View File

@@ -4,7 +4,9 @@ import { ApplicationService } from '@core/application';
import { BreadcrumbService } from '@core/breadcrumb';
import { DomainAvailabilityService, ItemData } from '@domain/availability';
import { DomainCatalogService } from '@domain/catalog';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ItemDTO, ResponseArgsOfItemDTO } from '@swagger/cat';
import { AvailabilityDTO, BranchDTO } from '@swagger/checkout';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';

View File

@@ -5,7 +5,9 @@ import { DomainAvailabilityService } from '@domain/availability';
import { DomainCatalogService } from '@domain/catalog';
import { DomainCheckoutService } from '@domain/checkout';
import { DomainOmsService } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ItemDTO } from '@swagger/cat';
import {
AddToShoppingCartDTO,

View File

@@ -7,7 +7,6 @@ import { ProductImageModule } from '@cdn/product-image';
import { RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { UiSpinnerModule } from '@ui/spinner';
import { ModalPrinterModule } from '@modal/printer';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { UiCheckboxModule } from '@ui/checkbox';
@@ -34,7 +33,6 @@ import { LoaderComponent, SkeletonLoaderComponent } from '@shared/components/loa
FormsModule,
ReactiveFormsModule,
UiSpinnerModule,
ModalPrinterModule,
UiFormControlModule,
UiInputModule,
UiCheckboxModule,

View File

@@ -2,7 +2,9 @@ import { Injectable } from '@angular/core';
import { UntypedFormGroup } from '@angular/forms';
import { ApplicationService } from '@core/application';
import { DomainCheckoutService } from '@domain/checkout';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { NotificationChannel, PayerDTO, ShoppingCartDTO, ShoppingCartItemDTO } from '@swagger/checkout';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { BehaviorSubject, Subject } from 'rxjs';

View File

@@ -4,7 +4,6 @@ import { CommonModule } from '@angular/common';
import { CheckoutSummaryComponent } from './checkout-summary.component';
import { PageCheckoutPipeModule } from '../pipes/page-checkout-pipe.module';
import { ProductImageModule } from '@cdn/product-image';
import { ModalPrinterModule } from '@modal/printer';
import { RouterModule } from '@angular/router';
import { UiCommonModule } from '@ui/common';
import { UiSpinnerModule } from '@ui/spinner';
@@ -18,7 +17,6 @@ import { AuthModule } from '@core/auth';
RouterModule,
PageCheckoutPipeModule,
ProductImageModule,
ModalPrinterModule,
IconModule,
UiCommonModule,
UiSpinnerModule,

View File

@@ -12,7 +12,9 @@ import {
} from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { DomainOmsService, DomainReceiptService } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { OrderDTO, OrderItemListItemDTO, ReceiptDTO, ReceiptType } from '@swagger/oms';
import { isEqual } from 'lodash';
import { combineLatest, NEVER, Subject, Observable } from 'rxjs';

View File

@@ -1,6 +1,8 @@
import { Injectable, OnDestroy } from '@angular/core';
import { DomainCustomerOrderService, DomainOmsService, OrderItemsContext } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { OrderDTO, OrderItemListItemDTO, OrderItemProcessingStatusValue, ReceiptDTO } from '@swagger/oms';
import { log } from '@utils/common';
import { isEqual } from 'lodash';

View File

@@ -1,6 +1,6 @@
import { BooleanInput, NumberInput, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
import { CdkMenuModule } from '@angular/cdk/menu';
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
import { Component, ChangeDetectionStrategy, Input, inject } from '@angular/core';
import { IconComponent } from '@shared/components/icon';
import { SharedMenuModule } from '@shared/components/menu';
import { combineLatest } from 'rxjs';
@@ -30,6 +30,8 @@ export interface CustomerMenuComponentState {
imports: [CdkMenuModule, SharedMenuModule, IconComponent, RouterLink, NgIf, AsyncPipe],
})
export class CustomerMenuComponent extends ComponentStore<CustomerMenuComponentState> {
private _navigation = inject(CustomerSearchNavigation);
@Input() set customerId(value: NumberInput) {
this.patchState({ customerId: coerceNumberProperty(value) });
}
@@ -100,7 +102,7 @@ export class CustomerMenuComponent extends ComponentStore<CustomerMenuComponentS
),
);
constructor(private _navigation: CustomerSearchNavigation) {
constructor() {
super({
showCustomerCard: true,
showCustomerDetails: true,

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output, ViewChild } from '@angular/core';
import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output, ViewChild, inject } from '@angular/core';
import { CustomerInfoDTO } from '@swagger/crm';
import { BooleanInput, NumberInput, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
import { CustomerCreateNavigation, CustomerSearchNavigation } from '@shared/services/navigation';
@@ -12,6 +12,9 @@ import { asapScheduler } from 'rxjs';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerResultListComponent {
public customerSearchNavigation = inject(CustomerSearchNavigation);
public customerCreateNavigation = inject(CustomerCreateNavigation);
private _compact: boolean;
@Input()
get compact() {
@@ -64,11 +67,6 @@ export class CustomerResultListComponent {
@Output()
scrollIndexChange = new EventEmitter<number>();
constructor(
public customerSearchNavigation: CustomerSearchNavigation,
public customerCreateNavigation: CustomerCreateNavigation,
) {}
scrolledIndexChange(index: number) {
if (index && this.customers.length <= this.viewport?.getRenderedRange()?.end) {
this.endReached.emit();

View File

@@ -14,7 +14,9 @@ import {
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { CacheService } from '@core/cache';
import { DomainCheckoutService } from '@domain/checkout';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { OptionDTO } from '@swagger/checkout';
import { UiCheckboxComponent } from '@ui/checkbox';
import { first, isBoolean, isString } from 'lodash';

View File

@@ -35,6 +35,16 @@ import { CustomerCreateNavigation, CustomerSearchNavigation } from '@shared/serv
@Directive()
export abstract class AbstractCreateCustomer implements OnInit, OnDestroy {
protected modal = inject(UiModalService);
protected activatedRoute = inject(ActivatedRoute);
protected router = inject(Router);
protected customerService = inject(CrmCustomerService);
protected addressVlidationModal = inject(AddressSelectionModalService);
protected breadcrumb = inject(BreadcrumbService);
protected cdr = inject(ChangeDetectorRef);
protected customerSearchNavigation = inject(CustomerSearchNavigation);
protected onDestroy$ = new Subject<void>();
abstract validateAddress?: boolean;
@@ -68,16 +78,7 @@ export abstract class AbstractCreateCustomer implements OnInit, OnDestroy {
readonly customerCreateNavigation = inject(CustomerCreateNavigation);
constructor(
protected activatedRoute: ActivatedRoute,
protected router: Router,
protected customerService: CrmCustomerService,
protected addressVlidationModal: AddressSelectionModalService,
protected modal: UiModalService,
protected breadcrumb: BreadcrumbService,
protected cdr: ChangeDetectorRef,
protected customerSearchNavigation: CustomerSearchNavigation,
) {
constructor() {
this._initProcessId$();
}

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
import { CheckboxComponent } from '@shared/components/checkbox';
import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { SelectModule } from '@shared/components/select';
@@ -36,6 +36,12 @@ import { GenderSettingsService } from '@shared/services/gender';
],
})
export class AddBillingAddressMainViewComponent {
private _customerService = inject(CrmCustomerService);
private _addressSelection = inject(AddressSelectionModalService);
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
public genderSettings = inject(GenderSettingsService);
formGroup = new FormGroup({
gender: new FormControl<Gender>(undefined, [Validators.required]),
title: new FormControl<string>(undefined),
@@ -57,14 +63,6 @@ export class AddBillingAddressMainViewComponent {
map(([processId, customerId]) => this._navigation.detailsRoute({ processId, customerId })),
);
constructor(
private _customerService: CrmCustomerService,
private _addressSelection: AddressSelectionModalService,
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
public genderSettings: GenderSettingsService,
) {}
async save() {
if (this.formGroup.invalid) {
this.formGroup.markAllAsTouched();

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, inject } from '@angular/core';
import { CheckboxComponent } from '@shared/components/checkbox';
import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { SelectModule } from '@shared/components/select';
@@ -36,6 +36,12 @@ import { GenderSettingsService } from '@shared/services/gender';
],
})
export class AddShippingAddressMainViewComponent implements OnInit, OnDestroy {
private _customerService = inject(CrmCustomerService);
private _addressSelection = inject(AddressSelectionModalService);
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
public genderSettings = inject(GenderSettingsService);
private _onDestroy = new Subject<void>();
detailsRoute$ = combineLatest([this._store.processId$, this._store.customerId$]).pipe(
@@ -63,14 +69,6 @@ export class AddShippingAddressMainViewComponent implements OnInit, OnDestroy {
isBusinessKonto$ = this._store.isBusinessKonto$;
constructor(
private _customerService: CrmCustomerService,
private _addressSelection: AddressSelectionModalService,
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
public genderSettings: GenderSettingsService,
) {}
ngOnInit() {
this._store.customer$.pipe(takeUntil(this._onDestroy)).subscribe(() => {
if (this._store.isBusinessKonto) {

View File

@@ -27,6 +27,13 @@ import { provideCancelSearchSubject } from '@shared/services/cancel-subject';
],
})
export class CustomerSearchComponent implements OnInit, OnDestroy {
private _store = inject(CustomerSearchStore);
private _activatedRoute = inject(ActivatedRoute);
private _router = inject(Router);
private _breadcrumbService = inject(BreadcrumbService);
private _navigation = inject(CustomerSearchNavigation);
private _createNavigation = inject(CustomerCreateNavigation);
private searchStore = inject(CustomerSearchStore);
keyEscPressed = toSignal(fromEvent(document, 'keydown').pipe(filter((e: KeyboardEvent) => e.key === 'Escape')));
@@ -74,14 +81,7 @@ export class CustomerSearchComponent implements OnInit, OnDestroy {
private _onDestroy$ = new Subject<void>();
constructor(
private _store: CustomerSearchStore,
private _activatedRoute: ActivatedRoute,
private _router: Router,
private _breadcrumbService: BreadcrumbService,
private _navigation: CustomerSearchNavigation,
private _createNavigation: CustomerCreateNavigation,
) {}
constructor() {}
ngOnInit(): void {
this.checkAndUpdateProcessId();

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, Host } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, Host, inject } from '@angular/core';
import { CustomerSearchStore } from '../../store';
import { CrmCustomerService } from '@domain/crm';
import { debounceTime, map, switchMap, takeUntil } from 'rxjs/operators';
@@ -6,7 +6,9 @@ import { Observable, Subject, combineLatest } from 'rxjs';
import { AssignedPayerDTO, CustomerDTO, ListResponseArgsOfAssignedPayerDTO } from '@swagger/crm';
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
import { CustomerPipesModule } from '@shared/pipes/customer';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { UiModalService } from '@ui/modal';
import { CustomerSearchNavigation } from '@shared/services/navigation';
import { RouterLink } from '@angular/router';
@@ -31,6 +33,12 @@ export class DetailsMainViewBillingAddressesComponent
extends ComponentStore<DetailsMainViewBillingAddressesComponentState>
implements OnInit, OnDestroy
{
private _host = inject(CustomerDetailsViewMainComponent, { host: true });
private _store = inject(CustomerSearchStore);
private _customerService = inject(CrmCustomerService);
private _modal = inject(UiModalService);
private _navigation = inject(CustomerSearchNavigation);
assignedPayers$ = this.select((state) => state.assignedPayers);
selectedPayer$ = this.select((state) => state.selectedPayer);
@@ -69,13 +77,7 @@ export class DetailsMainViewBillingAddressesComponent
),
);
constructor(
@Host() private _host: CustomerDetailsViewMainComponent,
private _store: CustomerSearchStore,
private _customerService: CrmCustomerService,
private _modal: UiModalService,
private _navigation: CustomerSearchNavigation,
) {
constructor() {
super({
assignedPayers: [],
selectedPayer: undefined,

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, Host } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, Host, inject } from '@angular/core';
import { CustomerSearchStore } from '../../store';
import { CrmCustomerService } from '@domain/crm';
import { map, switchMap, takeUntil } from 'rxjs/operators';
@@ -6,7 +6,9 @@ import { Observable, Subject, combineLatest } from 'rxjs';
import { CustomerDTO, ListResponseArgsOfAssignedPayerDTO, ShippingAddressDTO } from '@swagger/crm';
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
import { CustomerPipesModule } from '@shared/pipes/customer';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { UiModalService } from '@ui/modal';
import { CustomerSearchNavigation } from '@shared/services/navigation';
import { RouterLink } from '@angular/router';
@@ -30,6 +32,12 @@ export class DetailsMainViewDeliveryAddressesComponent
extends ComponentStore<DetailsMainViewDeliveryAddressesComponentState>
implements OnInit, OnDestroy
{
private _host = inject(CustomerDetailsViewMainComponent, { host: true });
private _store = inject(CustomerSearchStore);
private _customerService = inject(CrmCustomerService);
private _modal = inject(UiModalService);
private _navigation = inject(CustomerSearchNavigation);
shippingAddresses$ = this.select((state) => state.shippingAddresses);
selectedShippingAddress$ = this.select((state) => state.selectedShippingAddress);
@@ -87,13 +95,7 @@ export class DetailsMainViewDeliveryAddressesComponent
map(([isKundenkarte, isBusinessKonto, isMitarbeiter]) => isKundenkarte || isBusinessKonto || isMitarbeiter),
);
constructor(
@Host() private _host: CustomerDetailsViewMainComponent,
private _store: CustomerSearchStore,
private _customerService: CrmCustomerService,
private _modal: UiModalService,
private _navigation: CustomerSearchNavigation,
) {
constructor() {
super({
shippingAddresses: [],
selectedShippingAddress: undefined,

View File

@@ -30,6 +30,16 @@ export interface CustomerDetailsViewMainState {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerDetailsViewMainComponent extends ComponentStore<CustomerDetailsViewMainState> implements OnInit, OnDestroy {
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
private _checkoutService = inject(DomainCheckoutService);
private _modalService = inject(UiModalService);
private _application = inject(ApplicationService);
private _catalogNavigation = inject(ProductCatalogNavigationService);
private _checkoutNavigation = inject(CheckoutNavigationService);
private _router = inject(Router);
private _activatedRoute = inject(ActivatedRoute);
private _genderSettings = inject(GenderSettingsService);
private _onDestroy$ = new Subject<void>();
customerService = inject(CrmCustomerService);
@@ -189,18 +199,7 @@ export class CustomerDetailsViewMainComponent extends ComponentStore<CustomerDet
map(([type, hasCard]) => type === 'webshop' || hasCard),
);
constructor(
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
private _checkoutService: DomainCheckoutService,
private _modalService: UiModalService,
private _application: ApplicationService,
private _catalogNavigation: ProductCatalogNavigationService,
private _checkoutNavigation: CheckoutNavigationService,
private _router: Router,
private _activatedRoute: ActivatedRoute,
private _genderSettings: GenderSettingsService,
) {
constructor() {
super({ isBusy: false, shoppingCart: undefined, shippingAddress: undefined, payer: undefined });
}

View File

@@ -32,6 +32,14 @@ export interface EditBillingAddressMainViewState {
imports: [AsyncPipe, RouterLink, IconComponent, NgForOf, ReactiveFormsModule, SelectModule, FormControlComponent, CheckboxComponent],
})
export class EditBillingAddressMainViewComponent extends ComponentStore<EditBillingAddressMainViewState> implements OnInit, OnDestroy {
private _customerService = inject(CrmCustomerService);
private _addressSelection = inject(AddressSelectionModalService);
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
private _activatedRoute = inject(ActivatedRoute);
private _modal = inject(UiModalService);
public genderSettings = inject(GenderSettingsService);
private _onDestroy$ = new Subject<void>();
detailsRoute$ = combineLatest([this._store.processId$, this._store.customerId$]).pipe(
@@ -70,15 +78,7 @@ export class EditBillingAddressMainViewComponent extends ComponentStore<EditBill
return this.get((s) => s.payer);
}
constructor(
private _customerService: CrmCustomerService,
private _addressSelection: AddressSelectionModalService,
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
private _activatedRoute: ActivatedRoute,
private _modal: UiModalService,
public genderSettings: GenderSettingsService,
) {
constructor() {
super({ payer: undefined });
}

View File

@@ -1,6 +1,6 @@
import { Location } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { CrmCustomerService } from '@domain/crm';
@@ -18,6 +18,15 @@ import { GenderSettingsService } from '@shared/services/gender';
@Component({ template: '' })
export abstract class CustomerDataEditComponent implements OnInit {
private customerService = inject(CrmCustomerService);
private activatedRoute = inject(ActivatedRoute);
private fb = inject(UntypedFormBuilder);
private cdr = inject(ChangeDetectorRef);
private location = inject(Location);
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
public genderSettings = inject(GenderSettingsService);
customer$: Observable<CustomerDTO>;
customerId$: Observable<number>;
countries$: Observable<CountryDTO[]>;
@@ -37,17 +46,6 @@ export abstract class CustomerDataEditComponent implements OnInit {
afterInitForm?: (control: AbstractControl) => void;
constructor(
private customerService: CrmCustomerService,
private activatedRoute: ActivatedRoute,
private fb: UntypedFormBuilder,
private cdr: ChangeDetectorRef,
private location: Location,
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
public genderSettings: GenderSettingsService,
) {}
ngOnInit() {
this.customerId$ = this.activatedRoute.params.pipe(map((p) => Number(p['customerId'])));
this.customer$ = this.customerId$.pipe(

View File

@@ -42,6 +42,11 @@ export interface EditShippingAddressMainViewState {
})
export class EditShippingAddressMainViewComponent extends ComponentStore<EditShippingAddressMainViewState> implements OnInit, OnDestroy {
private _activatedRoute = inject(ActivatedRoute);
private _customerService = inject(CrmCustomerService);
private _addressSelection = inject(AddressSelectionModalService);
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
public genderSettings = inject(GenderSettingsService);
private _onDestroy = new Subject<void>();
@@ -81,13 +86,7 @@ export class EditShippingAddressMainViewComponent extends ComponentStore<EditShi
return this.get((s) => s.shippingAddress?.id);
}
constructor(
private _customerService: CrmCustomerService,
private _addressSelection: AddressSelectionModalService,
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
public genderSettings: GenderSettingsService,
) {
constructor() {
super({ shippingAddress: undefined });
}

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
import { Location } from '@angular/common';
import { CustomerSearchStore } from '../store';
import { Filter } from '@shared/components/filter';
@@ -14,6 +14,11 @@ import { injectCancelSearch } from '@shared/services/cancel-subject';
host: { class: 'page-customer-filter-main-view' },
})
export class CustomerFilterMainViewComponent {
private _store = inject(CustomerSearchStore);
private _location = inject(Location);
private _router = inject(Router);
private _customerSearchNavigation = inject(CustomerSearchNavigation);
cancelSearch = injectCancelSearch();
fetchingFilterSettings$ = this._store.fetchingFilter$;
@@ -37,12 +42,7 @@ export class CustomerFilterMainViewComponent {
});
}
constructor(
private _store: CustomerSearchStore,
private _location: Location,
private _router: Router,
private _customerSearchNavigation: CustomerSearchNavigation,
) {
constructor() {
this.cancelSearch();
}

View File

@@ -1,6 +1,8 @@
import { Component, ChangeDetectionStrategy, AfterViewInit } from '@angular/core';
import { Component, ChangeDetectionStrategy, AfterViewInit, inject } from '@angular/core';
import { CrmCustomerService } from '@domain/crm';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { HistoryDTO } from '@swagger/crm';
import { Observable, combineLatest } from 'rxjs';
import { map, switchMap, tap } from 'rxjs/operators';
@@ -19,6 +21,10 @@ export interface CustomerHistoryViewMainState {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerHistoryMainViewComponent extends ComponentStore<CustomerHistoryViewMainState> implements AfterViewInit {
private _store = inject(CustomerSearchStore);
private _customerService = inject(CrmCustomerService);
private _navigation = inject(CustomerSearchNavigation);
fetching$ = this.select((s) => s.fetching);
history$ = this.select((s) => s.history);
@@ -41,11 +47,7 @@ export class CustomerHistoryMainViewComponent extends ComponentStore<CustomerHis
customerNumber$ = this.customer$.pipe(map((customer) => customer?.customerNumber));
constructor(
private _store: CustomerSearchStore,
private _customerService: CrmCustomerService,
private _navigation: CustomerSearchNavigation,
) {
constructor() {
super({});
}

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, inject } from '@angular/core';
import { CustomerSearchStore } from '../store';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { Subject, combineLatest, of } from 'rxjs';
@@ -21,6 +21,11 @@ import { CustomerMenuComponent } from '../../components/customer-menu';
imports: [CustomerMenuComponent, KundenkarteComponent, NgFor, AsyncPipe, NgIf, IconComponent, RouterLink],
})
export class KundenkarteMainViewComponent implements OnInit, OnDestroy {
private _store = inject(CustomerSearchStore);
private _activatedRoute = inject(ActivatedRoute);
private _customerService = inject(CrmCustomerService);
private _navigation = inject(CustomerSearchNavigation);
private _onDestroy$ = new Subject<void>();
customerId$ = this._activatedRoute.params.pipe(map((params) => params.customerId));
@@ -47,13 +52,6 @@ export class KundenkarteMainViewComponent implements OnInit, OnDestroy {
map(([processId, customerId]) => this._navigation.detailsRoute({ processId, customerId })),
);
constructor(
private _store: CustomerSearchStore,
private _activatedRoute: ActivatedRoute,
private _customerService: CrmCustomerService,
private _navigation: CustomerSearchNavigation,
) {}
ngOnInit() {
this.customerId$.subscribe((customerId) => {
this._store.selectCustomer(customerId);

View File

@@ -1,5 +1,5 @@
import { AsyncPipe, CommonModule, NgIf } from '@angular/common';
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
import { RouterModule } from '@angular/router';
import { Filter, FilterModule } from '@shared/components/filter';
import { CustomerSearchStore } from '../store';
@@ -17,6 +17,9 @@ import { CustomerInfoDTO } from '@swagger/crm';
imports: [CommonModule, RouterModule, FilterModule, AsyncPipe, NgIf],
})
export class MainSideViewComponent {
private _store = inject(CustomerSearchStore);
private _customerCreateNavigation = inject(CustomerCreateNavigation);
message$ = this._store.message$;
filter$ = this._store.filter$;
@@ -45,11 +48,6 @@ export class MainSideViewComponent {
}),
);
constructor(
private _store: CustomerSearchStore,
private _customerCreateNavigation: CustomerCreateNavigation,
) {}
search(filter: Filter) {
this._store.setFilter(filter);
this._store.search({ resetScrollIndex: true, ignoreRestore: true });

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
import { CustomerSearchStore } from '../store';
import { Filter, FilterModule } from '@shared/components/filter';
import { map } from 'rxjs/operators';
@@ -21,6 +21,11 @@ import { CustomerInfoDTO } from '@swagger/crm';
imports: [AsyncPipe, RouterLink, FilterModule, NgIf, IconComponent, CustomerFilterMainViewModule],
})
export class CustomerMainViewComponent {
private _searchNavigation = inject(CustomerSearchNavigation);
private _customerCreateNavigation = inject(CustomerCreateNavigation);
private _store = inject(CustomerSearchStore);
private _router = inject(Router);
filterRoute$ = combineLatest([this._store.processId$, this._store.filter$]).pipe(
map(([processId, filter]) => {
const route = this._searchNavigation.filterRoute({ processId, comingFrom: this._router.url?.split('?')[0] });
@@ -66,13 +71,6 @@ export class CustomerMainViewComponent {
message$ = this._store.message$;
constructor(
private _searchNavigation: CustomerSearchNavigation,
private _customerCreateNavigation: CustomerCreateNavigation,
private _store: CustomerSearchStore,
private _router: Router,
) {}
search(filter: Filter) {
this._store.setFilter(filter);
this._store.search({ resetScrollIndex: true, ignoreRestore: true });

View File

@@ -1,6 +1,7 @@
import { Component, ChangeDetectionStrategy, AfterViewInit, OnInit, OnDestroy } from '@angular/core';
import { CrmCustomerService } from '@domain/crm';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, inject } from '@angular/core';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { HistoryDTO } from '@swagger/crm';
import { Observable, Subject, combineLatest } from 'rxjs';
import { map, switchMap, takeUntil, tap } from 'rxjs/operators';
@@ -29,6 +30,11 @@ export class CustomerOrderDetailsHistoryMainViewComponent
extends ComponentStore<CustomerHistoryViewMainState>
implements OnInit, OnDestroy
{
private _activvatedRoute = inject(ActivatedRoute);
private _store = inject(CustomerSearchStore);
private _omsService = inject(DomainOmsService);
private _navigation = inject(CustomerSearchNavigation);
private _onDestroy$ = new Subject<void>();
fetching$ = this.select((s) => s.fetching);
@@ -61,13 +67,7 @@ export class CustomerOrderDetailsHistoryMainViewComponent
),
);
constructor(
private _activvatedRoute: ActivatedRoute,
private _store: CustomerSearchStore,
private _customerService: CrmCustomerService,
private _omsService: DomainOmsService,
private _navigation: CustomerSearchNavigation,
) {
constructor() {
super({});
}

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, inject } from '@angular/core';
import { CustomerSearchStore } from '../store';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { map, takeUntil, tap } from 'rxjs/operators';
@@ -40,6 +40,11 @@ import { EnvironmentService } from '@core/environment';
],
})
export class OrderDetailsMainViewComponent implements OnInit, OnDestroy {
private _activateRoute = inject(ActivatedRoute);
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
private _env = inject(EnvironmentService);
orderId$ = this._activateRoute.params.pipe(map((params) => Number(params.orderId)));
order$ = this._store.order$;
@@ -87,13 +92,6 @@ export class OrderDetailsMainViewComponent implements OnInit, OnDestroy {
showItemList$ = this.showSelectedItem$.pipe(map((showSelectedItem) => !showSelectedItem));
constructor(
private _activateRoute: ActivatedRoute,
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
private _env: EnvironmentService,
) {}
ngOnInit(): void {
this.orderId$.pipe(takeUntil(this._onDestroy)).subscribe((orderId) => {
this._store.selectOrder(orderId);

View File

@@ -1,5 +1,5 @@
import { AsyncPipe, CurrencyPipe, DatePipe, NgIf } from '@angular/common';
import { Component, ChangeDetectionStrategy, Input, OnDestroy, OnInit } from '@angular/core';
import { Component, ChangeDetectionStrategy, Input, OnDestroy, OnInit, inject } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { ProductImagePipe } from '@cdn/product-image';
import { IconComponent } from '@shared/components/icon';
@@ -35,6 +35,10 @@ import { PaymentTypePipe } from '@shared/pipes/customer';
],
})
export class CustomerOrderItemListItemComponent implements OnInit, OnDestroy {
private _activatedRoute = inject(ActivatedRoute);
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
private _onDestroy = new Subject<void>();
private _orderItemSub = new BehaviorSubject<OrderItemDTO>(undefined);
@@ -69,12 +73,6 @@ export class CustomerOrderItemListItemComponent implements OnInit, OnDestroy {
processingStatus$ = this.orderItemSubsetItem$.pipe(map((subsetItem) => subsetItem?.processingStatus));
constructor(
private _activatedRoute: ActivatedRoute,
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
) {}
ngOnInit() {
this.customerId$.pipe(takeUntil(this._onDestroy)).subscribe((customerId) => {
this._store.selectCustomer({ customerId });

View File

@@ -24,10 +24,7 @@ export class OrderDetailsSideViewComponent {
selectedOrderItemId$ = this._store.selectedOrderItemId$;
constructor(
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
) {}
constructor(private _store: CustomerSearchStore) {}
selectOrderItem(orderItemId: number) {
this._store.selectOrderItemId(orderItemId);

View File

@@ -1,5 +1,5 @@
import { AsyncPipe, CurrencyPipe, DatePipe, NgIf } from '@angular/common';
import { Component, ChangeDetectionStrategy, Input, OnInit } from '@angular/core';
import { Component, ChangeDetectionStrategy, Input, inject } from '@angular/core';
import { OrderDestinationPipe, OrderProcessingStatusPipe } from '@shared/pipes/order';
import { AddressPipe } from '@shared/pipes/customer';
@@ -20,6 +20,9 @@ import { RouterLink } from '@angular/router';
imports: [DatePipe, OrderProcessingStatusPipe, OrderDestinationPipe, CurrencyPipe, NgIf, AddressPipe, AsyncPipe, RouterLink],
})
export class CustomerOrderListItemComponent {
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
private _orderListItemSub = new BehaviorSubject<OrderListItemDTO>(undefined);
@Input()
@@ -33,9 +36,4 @@ export class CustomerOrderListItemComponent {
orderDetailsRoute$ = combineLatest([this._store.processId$, this._store.customerId$, this._orderListItemSub]).pipe(
map(([processId, customerId, order]) => this._navigation.orderDetialsRoute({ processId, customerId, orderId: order?.id })),
);
constructor(
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
) {}
}

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, inject } from '@angular/core';
import { CustomerSearchStore } from '../store';
import { Subject, combineLatest } from 'rxjs';
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
@@ -20,6 +20,9 @@ import { CustomerMenuComponent } from '../../components/customer-menu';
imports: [CustomerMenuComponent, AsyncPipe, NgFor, NgIf, RouterLink, IconComponent, LoaderComponent, CustomerOrderListItemComponent],
})
export class CustomerOrdersMainViewComponent implements OnInit, OnDestroy {
private _store = inject(CustomerSearchStore);
private _navigation = inject(CustomerSearchNavigation);
private _onDestroy = new Subject<void>();
processId$ = this._store.processId$;
@@ -42,11 +45,6 @@ export class CustomerOrdersMainViewComponent implements OnInit, OnDestroy {
map(([processId, customerId]) => this._navigation.detailsRoute({ processId, customerId })),
);
constructor(
private _store: CustomerSearchStore,
private _navigation: CustomerSearchNavigation,
) {}
ngOnInit(): void {
this._store.customer$
.pipe(

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, AfterContentInit, ViewChild } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, AfterContentInit, ViewChild, inject } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { CustomerSearchStore } from '../store/customer-search.store';
import { BehaviorSubject, Subject, Subscription, combineLatest, race } from 'rxjs';
@@ -17,6 +17,11 @@ import { injectCancelSearch } from '@shared/services/cancel-subject';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerResultsMainViewComponent implements OnInit, OnDestroy, AfterContentInit {
private _store = inject(CustomerSearchStore);
private _router = inject(Router);
private _navigation = inject(CustomerSearchNavigation);
private _environment = inject(EnvironmentService);
cancelSearch = injectCancelSearch();
processId$ = this._store.processId$;
@@ -72,13 +77,6 @@ export class CustomerResultsMainViewComponent implements OnInit, OnDestroy, Afte
private _onDestroy$ = new Subject<void>();
constructor(
private _store: CustomerSearchStore,
private _router: Router,
private _navigation: CustomerSearchNavigation,
private _environment: EnvironmentService,
) {}
ngOnInit(): void {
this.routerEventsSubscription = this._router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnDestroy, OnInit, ViewChild, inject } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { CustomerSearchStore } from '../store/customer-search.store';
import { Subscription, BehaviorSubject, combineLatest, Subject, race } from 'rxjs';
@@ -17,6 +17,11 @@ import { injectCancelSearch } from '@shared/services/cancel-subject';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerResultsSideViewComponent implements OnInit, OnDestroy {
private _store = inject(CustomerSearchStore);
private _router = inject(Router);
private _navigation = inject(CustomerSearchNavigation);
private _location = inject(Location);
cancelSearch = injectCancelSearch();
processId$ = this._store.processId$;
@@ -75,13 +80,6 @@ export class CustomerResultsSideViewComponent implements OnInit, OnDestroy {
private _onDestroy$ = new Subject<void>();
constructor(
private _store: CustomerSearchStore,
private _router: Router,
private _navigation: CustomerSearchNavigation,
private _location: Location,
) {}
ngOnInit(): void {
this.routerEventsSubscription = this._router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {

View File

@@ -1,7 +1,9 @@
import { ComponentStore, tapResponse, OnStoreInit } from '@ngrx/component-store';
import { ComponentStore, OnStoreInit } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { CustomerSearchState } from './customer-search.state';
import * as S from './selectors';
import { Injectable, OnDestroy } from '@angular/core';
import { inject, Injectable, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { distinctUntilChanged, filter, switchMap, takeUntil, tap, withLatestFrom, delayWhen, first, map } from 'rxjs/operators';
import { CrmCustomerService } from '@domain/crm';
@@ -16,6 +18,10 @@ import { injectCancelSearchSubject } from '@shared/services/cancel-subject';
@Injectable()
export class CustomerSearchStore extends ComponentStore<CustomerSearchState> implements OnStoreInit, OnDestroy {
private _customerService = inject(CrmCustomerService);
private _omsService = inject(DomainOmsService);
private _modal = inject(UiModalService);
private _cancelSearch = injectCancelSearchSubject();
get processId() {
@@ -164,11 +170,7 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
selectedOrderItem$ = this.select(S.selectSelectedOrderItem);
constructor(
private _customerService: CrmCustomerService,
private _omsService: DomainOmsService,
private _modal: UiModalService,
) {
constructor() {
super({ customerListCount: 0 });
}

View File

@@ -1,15 +1,13 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Params, Router, RouterStateSnapshot } from '@angular/router';
import { DomainCheckoutService } from '@domain/checkout';
import { CustomerCreateFormData, decodeFormData } from '../create-customer';
import { CustomerCreateNavigation } from '@shared/services/navigation';
@Injectable({ providedIn: 'root' })
export class CustomerCreateGuard {
constructor(
private router: Router,
private checkoutService: DomainCheckoutService,
private customerCreateNavigation: CustomerCreateNavigation,
) {}
private router = inject(Router);
private checkoutService = inject(DomainCheckoutService);
private customerCreateNavigation = inject(CustomerCreateNavigation);
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
// exit with true if canActivateChild will be called

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { CrmCustomerService } from '@domain/crm';
import { AddressDTO } from '@swagger/crm';
import { UiModalService } from '@ui/modal';
@@ -7,10 +7,9 @@ import { DeprecatedAddressSelectionModalComponent } from './address-selection-mo
@Injectable({ providedIn: 'root' })
export class AddressSelectionModalService {
constructor(
private customerService: CrmCustomerService,
private modal: UiModalService,
) {}
private modal = inject(UiModalService);
constructor(private customerService: CrmCustomerService) {}
async validateAddress(address: AddressDTO): Promise<AddressDTO> {
if (address.street && address.streetNumber && address.zipCode && address.city && address.country) {

View File

@@ -1,7 +1,9 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { DomainGoodsService } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO } from '@swagger/oms';
import { isResponseArgs } from '@utils/object';
import { Subject } from 'rxjs';

View File

@@ -2,7 +2,9 @@ import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { DomainGoodsService } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO, QueryTokenDTO } from '@swagger/oms';
import { UiFilter } from '@ui/filter';
import { isResponseArgs } from '@utils/object';

View File

@@ -1,7 +1,9 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { DomainGoodsService } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO } from '@swagger/oms';
import { isResponseArgs } from '@utils/object';
import { Subject } from 'rxjs';

View File

@@ -2,7 +2,9 @@ import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { DomainAvailabilityService } from '@domain/availability';
import { DomainGoodsService } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO, QueryTokenDTO } from '@swagger/oms';
import { isResponseArgs } from '@utils/object';
import { Subject } from 'rxjs';

View File

@@ -1,42 +1,42 @@
import { RouterTestingModule } from '@angular/router/testing';
import { BreadcrumbService } from '@core/breadcrumb';
import { Spectator, createComponentFactory } from '@ngneat/spectator';
import { BreadcrumbComponent } from '@shared/components/breadcrumb';
import { UiIconModule } from '@ui/icon';
import { MockComponent } from 'ng-mocks';
import { GoodsInComponent } from './goods-in.component';
// import { RouterTestingModule } from '@angular/router/testing';
// import { BreadcrumbService } from '@core/breadcrumb';
// import { Spectator, createComponentFactory } from '@ngneat/spectator';
// import { BreadcrumbComponent } from '@shared/components/breadcrumb';
// import { UiIconModule } from '@ui/icon';
// import { MockComponent } from 'ng-mocks';
// import { GoodsInComponent } from './goods-in.component';
describe('GoodsInComponent', () => {
let spectator: Spectator<GoodsInComponent>;
let breadcrumbServiceMock = {
addBreadcrumbIfNotExists: jasmine.createSpy(),
};
// describe('GoodsInComponent', () => {
// let spectator: Spectator<GoodsInComponent>;
// let breadcrumbServiceMock = {
// addBreadcrumbIfNotExists: jasmine.createSpy(),
// };
const createComponent = createComponentFactory({
component: GoodsInComponent,
imports: [RouterTestingModule, UiIconModule],
declarations: [MockComponent(BreadcrumbComponent)],
});
// const createComponent = createComponentFactory({
// component: GoodsInComponent,
// imports: [RouterTestingModule, UiIconModule],
// declarations: [MockComponent(BreadcrumbComponent)],
// });
beforeEach(async () => {
spectator = createComponent({
providers: [{ provide: BreadcrumbService, useValue: breadcrumbServiceMock }],
});
});
// beforeEach(async () => {
// spectator = createComponent({
// providers: [{ provide: BreadcrumbService, useValue: breadcrumbServiceMock }],
// });
// });
// it('should create', () => {
// expect(spectator.component).toBeTruthy();
// });
// // it('should create', () => {
// // expect(spectator.component).toBeTruthy();
// // });
// describe('ngOnInit', () => {
// it('should call BreadcrumbService.addBreadcrumbIfNotExists', () => {
// expect(breadcrumbServiceMock.addBreadcrumbIfNotExists).toHaveBeenCalled();
// });
// });
// // describe('ngOnInit', () => {
// // it('should call BreadcrumbService.addBreadcrumbIfNotExists', () => {
// // expect(breadcrumbServiceMock.addBreadcrumbIfNotExists).toHaveBeenCalled();
// // });
// // });
// describe('shell-breadcrumb', () => {
// it('should render', () => {
// expect(spectator.query('shell-breadcrumb')).toBeVisible();
// });
// });
});
// // describe('shell-breadcrumb', () => {
// // it('should render', () => {
// // expect(spectator.query('shell-breadcrumb')).toBeVisible();
// // });
// // });
// });

View File

@@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
import { DomainAvailabilityService } from '@domain/availability';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ArrivalStatus, PackageItemDTO, StockInfoDTO } from '@swagger/wws';
import { Observable } from 'rxjs';
import { filter, switchMap } from 'rxjs/operators';

View File

@@ -1,6 +1,8 @@
import { Injectable, OnDestroy } from '@angular/core';
import { DomainPackageInspectionService, PackageStatusChangedEvent } from '@domain/package-inspection';
import { ComponentStore, OnStoreInit, tapResponse } from '@ngrx/component-store';
import { ComponentStore, OnStoreInit } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ListResponseArgsOfPackageDTO2, PackageDTO2, QuerySettingsDTO } from '@swagger/wws';
import { UiFilter } from '@ui/filter';
import { UiModalService } from '@ui/modal';

View File

@@ -1,4 +1,6 @@
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { PickupShelfDetailsState } from './pickup-shelf-details.state';
import { Observable, combineLatest, from } from 'rxjs';
import {

View File

@@ -3,7 +3,9 @@ import { ActivatedRoute, Router } from '@angular/router';
import { CacheService } from '@core/cache';
import { Config } from '@core/config';
import { DomainRemissionService, RemissionListItem } from '@domain/remission';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ReturnItemDTO, ReturnSuggestionDTO, SupplierDTO } from '@swagger/remi';
import { UiFilter } from '@ui/filter';
import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';

View File

@@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
import { DomainRemissionService } from '@domain/remission';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ReturnDTO } from '@swagger/remi';
import { Observable, Subject } from 'rxjs';
import { switchMap } from 'rxjs/operators';

View File

@@ -4,7 +4,9 @@ import { BreadcrumbService } from '@core/breadcrumb';
import { CacheService } from '@core/cache';
import { Config } from '@core/config';
import { DomainRemissionService } from '@domain/remission';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { ReturnDTO } from '@swagger/remi';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { NEVER, Observable } from 'rxjs';

View File

@@ -1,6 +1,8 @@
import { Injectable, OnDestroy } from '@angular/core';
import { DomainTaskCalendarService } from '@domain/task-calendar';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { DisplayInfoDTO, InputDTO, QuerySettingsDTO } from '@swagger/eis';
import { CalendarIndicator } from '@ui/calendar';
import { DateAdapter } from '@ui/common';

View File

@@ -1,59 +1 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/
import 'zone.js';

View File

@@ -1,204 +1,204 @@
import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { AuthService } from '@core/auth';
import { DomainAvailabilityService } from '@domain/availability';
import { createComponentFactory, Spectator } from '@ngneat/spectator';
import { UiAutocompleteModule } from '@ui/autocomplete';
import { UiCommonModule } from '@ui/common';
import { UiIconModule } from '@ui/icon';
import { UiModalService } from '@ui/modal';
import { BranchSelectorComponent } from './branch-selector.component';
import { BranchSelectorStore } from './branch-selector.store';
import { EmptyIconLoader, IconLoader, provideIcon } from '@shared/components/icon';
// import { CommonModule } from '@angular/common';
// import { HttpClient } from '@angular/common/http';
// import { FormsModule } from '@angular/forms';
// import { AuthService } from '@core/auth';
// import { DomainAvailabilityService } from '@domain/availability';
// import { createComponentFactory, Spectator } from '@ngneat/spectator';
// import { UiAutocompleteModule } from '@ui/autocomplete';
// import { UiCommonModule } from '@ui/common';
// import { UiIconModule } from '@ui/icon';
// import { UiModalService } from '@ui/modal';
// import { BranchSelectorComponent } from './branch-selector.component';
// import { BranchSelectorStore } from './branch-selector.store';
// import { EmptyIconLoader, IconLoader, provideIcon } from '@shared/components/icon';
describe('BranchSelectorComponent', () => {
let spectator: Spectator<BranchSelectorComponent>;
let branchSelectorStoreMock: jasmine.SpyObj<BranchSelectorStore>;
// describe('BranchSelectorComponent', () => {
// let spectator: Spectator<BranchSelectorComponent>;
// let branchSelectorStoreMock: jasmine.SpyObj<BranchSelectorStore>;
const createComponent = createComponentFactory({
component: BranchSelectorComponent,
imports: [UiCommonModule, CommonModule, FormsModule, UiIconModule, UiAutocompleteModule],
mocks: [DomainAvailabilityService, UiModalService, HttpClient, AuthService],
providers: [provideIcon({ provide: IconLoader, useClass: EmptyIconLoader })],
});
// const createComponent = createComponentFactory({
// component: BranchSelectorComponent,
// imports: [UiCommonModule, CommonModule, FormsModule, UiIconModule, UiAutocompleteModule],
// mocks: [DomainAvailabilityService, UiModalService, HttpClient, AuthService],
// providers: [provideIcon({ provide: IconLoader, useClass: EmptyIconLoader })],
// });
beforeEach(() => {
spectator = createComponent();
branchSelectorStoreMock = spectator.inject(BranchSelectorStore, true);
});
// beforeEach(() => {
// spectator = createComponent();
// branchSelectorStoreMock = spectator.inject(BranchSelectorStore, true);
// });
it('should create', () => {
expect(spectator.component).toBeTruthy();
});
// it('should create', () => {
// expect(spectator.component).toBeTruthy();
// });
describe('value', () => {
it('should call setBranch(value)', () => {
const value = { id: 1 };
const setBranchSpy = spyOn(spectator.component, 'setBranch');
spectator.component.value = value;
expect(setBranchSpy).toHaveBeenCalledWith(value);
});
});
// describe('value', () => {
// it('should call setBranch(value)', () => {
// const value = { id: 1 };
// const setBranchSpy = spyOn(spectator.component, 'setBranch');
// spectator.component.value = value;
// expect(setBranchSpy).toHaveBeenCalledWith(value);
// });
// });
describe('disabled', () => {
it('should set disabled based on Input value', () => {
const disabled = true;
spectator.setInput('disabled', disabled);
expect(spectator.component.disabled).toBe(disabled);
});
});
// describe('disabled', () => {
// it('should set disabled based on Input value', () => {
// const disabled = true;
// spectator.setInput('disabled', disabled);
// expect(spectator.component.disabled).toBe(disabled);
// });
// });
// describe('branchType', () => {
// it('should set branchType based on Input value', () => {
// const branchType = 4;
// spectator.setInput('branchType', branchType);
// expect(spectator.component.branchType).toBe(branchType);
// });
// });
// // describe('branchType', () => {
// // it('should set branchType based on Input value', () => {
// // const branchType = 4;
// // spectator.setInput('branchType', branchType);
// // expect(spectator.component.branchType).toBe(branchType);
// // });
// // });
describe('registerOnChange()', () => {
it('should assign new fn to onChange', () => {
const newFn = () => {};
spectator.component.registerOnChange(newFn);
expect(spectator.component.onChange).toEqual(newFn);
});
});
// describe('registerOnChange()', () => {
// it('should assign new fn to onChange', () => {
// const newFn = () => {};
// spectator.component.registerOnChange(newFn);
// expect(spectator.component.onChange).toEqual(newFn);
// });
// });
describe('registerOnTouched()', () => {
it('should assign new fn to onTouched', () => {
const newFn = () => {};
spectator.component.registerOnTouched(newFn);
expect(spectator.component.onTouched).toEqual(newFn);
});
});
// describe('registerOnTouched()', () => {
// it('should assign new fn to onTouched', () => {
// const newFn = () => {};
// spectator.component.registerOnTouched(newFn);
// expect(spectator.component.onTouched).toEqual(newFn);
// });
// });
describe('setDisabledState()', () => {
it('should assign new value to disabled', () => {
const newValue = true;
spectator.component.setDisabledState(newValue);
expect(spectator.component.disabled).toBe(newValue);
});
});
// describe('setDisabledState()', () => {
// it('should assign new value to disabled', () => {
// const newValue = true;
// spectator.component.setDisabledState(newValue);
// expect(spectator.component.disabled).toBe(newValue);
// });
// });
describe('ngOnInit()', () => {
it('should call store.loadBranches()', () => {
spyOn(branchSelectorStoreMock, 'loadBranches');
spectator.component.ngOnInit();
expect(branchSelectorStoreMock.loadBranches).toHaveBeenCalled();
});
});
// describe('ngOnInit()', () => {
// it('should call store.loadBranches()', () => {
// spyOn(branchSelectorStoreMock, 'loadBranches');
// spectator.component.ngOnInit();
// expect(branchSelectorStoreMock.loadBranches).toHaveBeenCalled();
// });
// });
describe('ngAfterViewInit()', () => {
it('should call initAutocomplete()', () => {
const initAutocompleteSpy = spyOn(spectator.component, 'initAutocomplete');
spectator.component.ngAfterViewInit();
expect(initAutocompleteSpy).toHaveBeenCalled();
});
});
// describe('ngAfterViewInit()', () => {
// it('should call initAutocomplete()', () => {
// const initAutocompleteSpy = spyOn(spectator.component, 'initAutocomplete');
// spectator.component.ngAfterViewInit();
// expect(initAutocompleteSpy).toHaveBeenCalled();
// });
// });
describe('initAutocomplete()', () => {
// it('should call complete.asObservable()', () => {
// const completeSpy = spyOn(spectator.component.complete, 'asObservable').and.returnValue(of('test'));
// spectator.component.initAutocomplete();
// expect(completeSpy).toHaveBeenCalled();
// });
// it('should call filterBranchesFn({ query, branches })', () => {
// const branches = [{ id: 1 }, { id: 2 }];
// const query = 'Test';
// branchSelectorStoreMock.setBranches(branches);
// const filterBranchesFnSpy = spyOn(spectator.component, 'filterBranchesFn');
// spectator.component.initAutocomplete();
// spectator.component.branches$.pipe(take(1)).subscribe(() => {
// expect(filterBranchesFnSpy).toHaveBeenCalledWith({ query, branches });
// });
// spectator.component.complete.next(query);
// });
// it('should call sortAutocompleteFn with BranchDTO[]', () => {
// const branches = [{ id: 1 }, { id: 2 }];
// const query = 'Test';
// spyOn(spectator.component, 'initAutocompleteFn').and.returnValue(branches);
// const sortAutocompleteFnSpy = spyOn(spectator.component, 'sortAutocompleteFn');
// spectator.component.initAutocomplete();
// spectator.component.complete.next(query);
// expect(sortAutocompleteFnSpy).toHaveBeenCalledWith(branches);
// });
});
// describe('initAutocomplete()', () => {
// // it('should call complete.asObservable()', () => {
// // const completeSpy = spyOn(spectator.component.complete, 'asObservable').and.returnValue(of('test'));
// // spectator.component.initAutocomplete();
// // expect(completeSpy).toHaveBeenCalled();
// // });
// // it('should call filterBranchesFn({ query, branches })', () => {
// // const branches = [{ id: 1 }, { id: 2 }];
// // const query = 'Test';
// // branchSelectorStoreMock.setBranches(branches);
// // const filterBranchesFnSpy = spyOn(spectator.component, 'filterBranchesFn');
// // spectator.component.initAutocomplete();
// // spectator.component.branches$.pipe(take(1)).subscribe(() => {
// // expect(filterBranchesFnSpy).toHaveBeenCalledWith({ query, branches });
// // });
// // spectator.component.complete.next(query);
// // });
// // it('should call sortAutocompleteFn with BranchDTO[]', () => {
// // const branches = [{ id: 1 }, { id: 2 }];
// // const query = 'Test';
// // spyOn(spectator.component, 'initAutocompleteFn').and.returnValue(branches);
// // const sortAutocompleteFnSpy = spyOn(spectator.component, 'sortAutocompleteFn');
// // spectator.component.initAutocomplete();
// // spectator.component.complete.next(query);
// // expect(sortAutocompleteFnSpy).toHaveBeenCalledWith(branches);
// // });
// });
// describe('initAutocompleteFn()', () => {
// it('should call filterAutocompleteFn({ query, branches }) if query.length > 1', () => {
// const query = 'test';
// const branches = [{ id: 1 }, { id: 2 }];
// // describe('initAutocompleteFn()', () => {
// // it('should call filterAutocompleteFn({ query, branches }) if query.length > 1', () => {
// // const query = 'test';
// // const branches = [{ id: 1 }, { id: 2 }];
// spectator.component.initAutocompleteFn({ query, branches });
// expect(spectator.component.complete.asObservable).toHaveBeenCalled();
// });
// // spectator.component.initAutocompleteFn({ query, branches });
// // expect(spectator.component.complete.asObservable).toHaveBeenCalled();
// // });
// it('should not call filterAutocompleteFn({ query, branches }) if query.length <= 1 and return branches', () => {});
// });
// // it('should not call filterAutocompleteFn({ query, branches }) if query.length <= 1 and return branches', () => {});
// // });
// describe('filterAutocompleteFn()', () => {});
// // describe('filterAutocompleteFn()', () => {});
// it('should not emit search with the current query when key is ArrowUp or ArrowDown', () => {
// spectator.component.query = 'my query';
// let searchResult;
// spectator.output('search').subscribe((search) => (searchResult = search));
// spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowUp' }));
// spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowDown' }));
// expect(searchResult).toBeUndefined();
// });
// // it('should not emit search with the current query when key is ArrowUp or ArrowDown', () => {
// // spectator.component.query = 'my query';
// // let searchResult;
// // spectator.output('search').subscribe((search) => (searchResult = search));
// // spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowUp' }));
// // spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowDown' }));
// // expect(searchResult).toBeUndefined();
// // });
// it('should call handleArrowUpDownEvent when key is ArrowUp', () => {
// spyOn(spectator.component, 'handleArrowUpDownEvent');
// spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowUp' }));
// expect(spectator.component.handleArrowUpDownEvent).toHaveBeenCalled();
// });
// // it('should call handleArrowUpDownEvent when key is ArrowUp', () => {
// // spyOn(spectator.component, 'handleArrowUpDownEvent');
// // spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowUp' }));
// // expect(spectator.component.handleArrowUpDownEvent).toHaveBeenCalled();
// // });
// it('should call handleArrowUpDownEvent when key is ArrowDown', () => {
// spyOn(spectator.component, 'handleArrowUpDownEvent');
// spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowDown' }));
// expect(spectator.component.handleArrowUpDownEvent).toHaveBeenCalled();
// });
// // it('should call handleArrowUpDownEvent when key is ArrowDown', () => {
// // spyOn(spectator.component, 'handleArrowUpDownEvent');
// // spectator.component.onKeyup(new KeyboardEvent('', { key: 'ArrowDown' }));
// // expect(spectator.component.handleArrowUpDownEvent).toHaveBeenCalled();
// // });
// it('should not call handleArrowUpDownEvent when key is Enter', () => {
// spyOn(spectator.component, 'handleArrowUpDownEvent');
// spectator.component.onKeyup(new KeyboardEvent('', { key: 'Enter' }));
// expect(spectator.component.handleArrowUpDownEvent).not.toHaveBeenCalled();
// });
// });
// // it('should not call handleArrowUpDownEvent when key is Enter', () => {
// // spyOn(spectator.component, 'handleArrowUpDownEvent');
// // spectator.component.onKeyup(new KeyboardEvent('', { key: 'Enter' }));
// // expect(spectator.component.handleArrowUpDownEvent).not.toHaveBeenCalled();
// // });
// // });
// describe('with autocomplete', () => {
// const testItems = [
// { name: 'testbranch1', key: 'testkey1' },
// { name: 'testbranch2', key: 'testkey2' },
// ];
// // describe('with autocomplete', () => {
// // const testItems = [
// // { name: 'testbranch1', key: 'testkey1' },
// // { name: 'testbranch2', key: 'testkey2' },
// // ];
// beforeEach(() => {
// spectator = createHostWithAutocomplete(undefined, {
// hostProps: {
// items: testItems,
// },
// });
// });
// // beforeEach(() => {
// // spectator = createHostWithAutocomplete(undefined, {
// // hostProps: {
// // items: testItems,
// // },
// // });
// // });
// describe('handleArrowUpDownEvent', () => {
// it('should call handleKeyboardEvent with the event', () => {
// const event = new KeyboardEvent('keyup');
// spyOn(spectator.component.autocompleteComponent, 'handleKeyboardEvent');
// spectator.component.handleArrowUpDownEvent(event);
// // describe('handleArrowUpDownEvent', () => {
// // it('should call handleKeyboardEvent with the event', () => {
// // const event = new KeyboardEvent('keyup');
// // spyOn(spectator.component.autocompleteComponent, 'handleKeyboardEvent');
// // spectator.component.handleArrowUpDownEvent(event);
// expect(spectator.component.autocompleteComponent.handleKeyboardEvent).toHaveBeenCalledWith(event);
// });
// // expect(spectator.component.autocompleteComponent.handleKeyboardEvent).toHaveBeenCalledWith(event);
// // });
// it('should call setQuery when autocomplete.selectedItem is set', () => {
// const event = new KeyboardEvent('keyup');
// spyOn(spectator.component, 'setQuery');
// // it('should call setQuery when autocomplete.selectedItem is set', () => {
// // const event = new KeyboardEvent('keyup');
// // spyOn(spectator.component, 'setQuery');
// spectator.component.autocompleteComponent.listKeyManager.setFirstItemActive();
// // spectator.component.autocompleteComponent.listKeyManager.setFirstItemActive();
// spectator.component.handleArrowUpDownEvent(event);
// expect(spectator.component.setQuery).toHaveBeenCalledWith(testItems[0].key + ' - ' + testItems[0].name);
// });
// });
// });
});
// // spectator.component.handleArrowUpDownEvent(event);
// // expect(spectator.component.setQuery).toHaveBeenCalledWith(testItems[0].key + ' - ' + testItems[0].name);
// // });
// // });
// // });
// });

View File

@@ -1,347 +1,347 @@
import { AuthService } from '@core/auth';
import { DomainAvailabilityService } from '@domain/availability';
import { OpenStreetMap } from '@external/openstreetmap';
import { createServiceFactory, createSpyObject, SpectatorService, SpyObject } from '@ngneat/spectator';
import { BranchType } from '@swagger/checkout';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { of, throwError } from 'rxjs';
import { BranchSelectorStore } from './branch-selector.store';
// import { AuthService } from '@core/auth';
// import { DomainAvailabilityService } from '@domain/availability';
// import { OpenStreetMap } from '@external/openstreetmap';
// import { createServiceFactory, createSpyObject, SpectatorService, SpyObject } from '@ngneat/spectator';
// import { BranchType } from '@swagger/checkout';
// import { UiErrorModalComponent, UiModalService } from '@ui/modal';
// import { of, throwError } from 'rxjs';
// import { BranchSelectorStore } from './branch-selector.store';
describe('BranchSelectorStore', () => {
let spectator: SpectatorService<BranchSelectorStore>;
let availabilityServiceMock: SpyObject<DomainAvailabilityService>;
let uiModalServiceMock: SpyObject<UiModalService>;
// describe('BranchSelectorStore', () => {
// let spectator: SpectatorService<BranchSelectorStore>;
// let availabilityServiceMock: SpyObject<DomainAvailabilityService>;
// let uiModalServiceMock: SpyObject<UiModalService>;
const createService = createServiceFactory({
service: BranchSelectorStore,
mocks: [OpenStreetMap, AuthService],
});
// const createService = createServiceFactory({
// service: BranchSelectorStore,
// mocks: [OpenStreetMap, AuthService],
// });
beforeEach(() => {
availabilityServiceMock = createSpyObject(DomainAvailabilityService);
availabilityServiceMock.getBranches.and.returnValue(of([]));
availabilityServiceMock.getDefaultBranch.and.returnValue(of({}));
// beforeEach(() => {
// availabilityServiceMock = createSpyObject(DomainAvailabilityService);
// availabilityServiceMock.getBranches.and.returnValue(of([]));
// availabilityServiceMock.getDefaultBranch.and.returnValue(of({}));
uiModalServiceMock = createSpyObject(UiModalService);
// uiModalServiceMock = createSpyObject(UiModalService);
uiModalServiceMock = createSpyObject(UiModalService);
// uiModalServiceMock = createSpyObject(UiModalService);
spectator = createService({
providers: [
{ provide: DomainAvailabilityService, useValue: availabilityServiceMock },
{ provide: UiModalService, useValue: uiModalServiceMock },
],
});
});
// spectator = createService({
// providers: [
// { provide: DomainAvailabilityService, useValue: availabilityServiceMock },
// { provide: UiModalService, useValue: uiModalServiceMock },
// ],
// });
// });
it('should create', () => {
expect(spectator.service).toBeTruthy();
});
// it('should create', () => {
// expect(spectator.service).toBeTruthy();
// });
describe('get query', () => {
it('should return the query', () => {
const query = 'test';
spectator.service.setQuery(query);
expect(spectator.service.query).toBe(query);
});
});
// describe('get query', () => {
// it('should return the query', () => {
// const query = 'test';
// spectator.service.setQuery(query);
// expect(spectator.service.query).toBe(query);
// });
// });
describe('get query$', () => {
it('should return the query$', () => {
const query = 'test';
spectator.service.setQuery(query);
// describe('get query$', () => {
// it('should return the query$', () => {
// const query = 'test';
// spectator.service.setQuery(query);
spectator.service.query$
.subscribe((q) => {
expect(q).toBe(query);
})
.unsubscribe();
});
});
// spectator.service.query$
// .subscribe((q) => {
// expect(q).toBe(query);
// })
// .unsubscribe();
// });
// });
describe('get fetching', () => {
it('should return the fetching', () => {
const fetching = true;
spectator.service.setFetching(fetching);
expect(spectator.service.fetching).toBe(fetching);
});
});
// describe('get fetching', () => {
// it('should return the fetching', () => {
// const fetching = true;
// spectator.service.setFetching(fetching);
// expect(spectator.service.fetching).toBe(fetching);
// });
// });
describe('get fetching$', () => {
it('should return the fetching$', () => {
const fetching = true;
spectator.service.setFetching(fetching);
// describe('get fetching$', () => {
// it('should return the fetching$', () => {
// const fetching = true;
// spectator.service.setFetching(fetching);
spectator.service.fetching$
.subscribe((f) => {
expect(f).toBe(fetching);
})
.unsubscribe();
});
});
// spectator.service.fetching$
// .subscribe((f) => {
// expect(f).toBe(fetching);
// })
// .unsubscribe();
// });
// });
// describe('get branches', () => {
// it('should return the branches', () => {
// const branches = [{}, {}];
// spectator.service.setBranches(branches);
// expect(spectator.service.branches).toBe(branches);
// });
// });
// // describe('get branches', () => {
// // it('should return the branches', () => {
// // const branches = [{}, {}];
// // spectator.service.setBranches(branches);
// // expect(spectator.service.branches).toBe(branches);
// // });
// // });
// describe('get branches$', () => {
// it('should return the branches$', () => {
// const branches = [{}, {}];
// spectator.service.setBranches(branches);
// // describe('get branches$', () => {
// // it('should return the branches$', () => {
// // const branches = [{}, {}];
// // spectator.service.setBranches(branches);
// spectator.service.branches$
// .subscribe((b) => {
// expect(b).toBe(branches);
// })
// .unsubscribe();
// });
// });
// // spectator.service.branches$
// // .subscribe((b) => {
// // expect(b).toBe(branches);
// // })
// // .unsubscribe();
// // });
// // });
describe('get selectedBranch', () => {
it('should return the selectedBranch', () => {
const selectedBranch = { id: 123 };
spectator.service.setSelectedBranch(selectedBranch);
expect(spectator.service.selectedBranch).toEqual(selectedBranch);
});
});
// describe('get selectedBranch', () => {
// it('should return the selectedBranch', () => {
// const selectedBranch = { id: 123 };
// spectator.service.setSelectedBranch(selectedBranch);
// expect(spectator.service.selectedBranch).toEqual(selectedBranch);
// });
// });
describe('get selectedBranch$', () => {
it('should return the selectedBranch$', () => {
const selectedBranch = { id: 123 };
spectator.service.setSelectedBranch(selectedBranch);
// describe('get selectedBranch$', () => {
// it('should return the selectedBranch$', () => {
// const selectedBranch = { id: 123 };
// spectator.service.setSelectedBranch(selectedBranch);
spectator.service.selectedBranch$
.subscribe((sb) => {
expect(sb).toEqual(selectedBranch);
})
.unsubscribe();
});
});
// spectator.service.selectedBranch$
// .subscribe((sb) => {
// expect(sb).toEqual(selectedBranch);
// })
// .unsubscribe();
// });
// });
// describe('get branchType', () => {
// it('should return the branchType', () => {
// const branchType = 1;
// spectator.service.setBranchType(branchType);
// expect(spectator.service.branchType).toEqual(branchType);
// });
// });
// // describe('get branchType', () => {
// // it('should return the branchType', () => {
// // const branchType = 1;
// // spectator.service.setBranchType(branchType);
// // expect(spectator.service.branchType).toEqual(branchType);
// // });
// // });
// describe('get branchType$', () => {
// it('should return the branchType$', () => {
// const branchType = 1;
// spectator.service.setBranchType(branchType);
// // describe('get branchType$', () => {
// // it('should return the branchType$', () => {
// // const branchType = 1;
// // spectator.service.setBranchType(branchType);
// spectator.service.branchType$
// .subscribe((bt) => {
// expect(bt).toEqual(branchType);
// })
// .unsubscribe();
// });
// });
// // spectator.service.branchType$
// // .subscribe((bt) => {
// // expect(bt).toEqual(branchType);
// // })
// // .unsubscribe();
// // });
// // });
describe('loadBranches', () => {
const branches = [{ id: 1 }, { id: 2 }];
// describe('loadBranches', () => {
// const branches = [{ id: 1 }, { id: 2 }];
beforeEach(() => {
availabilityServiceMock.getBranches.and.returnValue(of(branches));
});
// beforeEach(() => {
// availabilityServiceMock.getBranches.and.returnValue(of(branches));
// });
it('should call setFetching(true)', () => {
spyOn(spectator.service, 'setFetching');
spectator.service.loadBranches();
expect(spectator.service.setFetching).toHaveBeenCalledWith(true);
});
// it('should call setFetching(true)', () => {
// spyOn(spectator.service, 'setFetching');
// spectator.service.loadBranches();
// expect(spectator.service.setFetching).toHaveBeenCalledWith(true);
// });
it('should call _availabilityService.getBranches()', () => {
spectator.service.loadBranches();
expect(availabilityServiceMock.getBranches).toHaveBeenCalled();
});
// it('should call _availabilityService.getBranches()', () => {
// spectator.service.loadBranches();
// expect(availabilityServiceMock.getBranches).toHaveBeenCalled();
// });
it('should call loadBranchesResponseFn({ response, selectedBranch, branchType, currentBranch })', () => {
const selectedBranch = { id: 123 };
const branchType = 1;
const currentBranch = { id: 9 };
availabilityServiceMock.getDefaultBranch.and.returnValue(of(currentBranch));
spectator.service.setSelectedBranch(selectedBranch);
spectator.service.setBranchType(branchType);
const loadBranchesResponseFnSpy = spyOn(spectator.service, 'loadBranchesResponseFn');
spectator.service.loadBranches();
expect(loadBranchesResponseFnSpy).toHaveBeenCalledWith({ response: branches, selectedBranch });
});
// it('should call loadBranchesResponseFn({ response, selectedBranch, branchType, currentBranch })', () => {
// const selectedBranch = { id: 123 };
// const branchType = 1;
// const currentBranch = { id: 9 };
// availabilityServiceMock.getDefaultBranch.and.returnValue(of(currentBranch));
// spectator.service.setSelectedBranch(selectedBranch);
// spectator.service.setBranchType(branchType);
// const loadBranchesResponseFnSpy = spyOn(spectator.service, 'loadBranchesResponseFn');
// spectator.service.loadBranches();
// expect(loadBranchesResponseFnSpy).toHaveBeenCalledWith({ response: branches, selectedBranch });
// });
it('should call loadBranchesErrorFn(error) if error got thrown', () => {
const error = new Error('Error message');
const loadBranchesErrorFnSpy = spyOn(spectator.service, 'loadBranchesErrorFn');
availabilityServiceMock.getBranches.and.returnValue(throwError(error));
spectator.service.loadBranches();
expect(loadBranchesErrorFnSpy).toHaveBeenCalledWith(error);
});
});
// it('should call loadBranchesErrorFn(error) if error got thrown', () => {
// const error = new Error('Error message');
// const loadBranchesErrorFnSpy = spyOn(spectator.service, 'loadBranchesErrorFn');
// availabilityServiceMock.getBranches.and.returnValue(throwError(error));
// spectator.service.loadBranches();
// expect(loadBranchesErrorFnSpy).toHaveBeenCalledWith(error);
// });
// });
describe('loadBranchesResponseFn()', () => {
let branches = [];
let branchType: BranchType = 1;
// describe('loadBranchesResponseFn()', () => {
// let branches = [];
// let branchType: BranchType = 1;
beforeEach(() => {
branches = [
{ id: 1, branchType: 1 },
{ id: 2, branchType: 1 },
];
branchType = 1;
});
// beforeEach(() => {
// branches = [
// { id: 1, branchType: 1 },
// { id: 2, branchType: 1 },
// ];
// branchType = 1;
// });
// it('should call _filter({ branches: response })', () => {
// const filterBranchesSpy = spyOn<any>(spectator.service, '_filter');
// spectator.service.loadBranchesResponseFn({ response: branches });
// expect(filterBranchesSpy).toHaveBeenCalledWith({ branches });
// });
// // it('should call _filter({ branches: response })', () => {
// // const filterBranchesSpy = spyOn<any>(spectator.service, '_filter');
// // spectator.service.loadBranchesResponseFn({ response: branches });
// // expect(filterBranchesSpy).toHaveBeenCalledWith({ branches });
// // });
// it('should call setBranches() with branches after filtering', () => {
// spyOn<any>(spectator.service, '_filter').and.returnValue([{ id: 1 }]);
// const setBranchesSpy = spyOn(spectator.service, 'setBranches');
// spectator.service.loadBranchesResponseFn({ response: branches });
// expect(setBranchesSpy).toHaveBeenCalledWith([{ id: 1 }]);
// });
// // it('should call setBranches() with branches after filtering', () => {
// // spyOn<any>(spectator.service, '_filter').and.returnValue([{ id: 1 }]);
// // const setBranchesSpy = spyOn(spectator.service, 'setBranches');
// // spectator.service.loadBranchesResponseFn({ response: branches });
// // expect(setBranchesSpy).toHaveBeenCalledWith([{ id: 1 }]);
// // });
// it('should call setBranches() with default [] if getBranches() return undefined', () => {
// spyOn<any>(spectator.service, '_filter').and.returnValue([]);
// const setBranchesSpy = spyOn(spectator.service, 'setBranches');
// spectator.service.loadBranchesResponseFn({ response: branches });
// expect(setBranchesSpy).toHaveBeenCalledWith([]);
// });
// // it('should call setBranches() with default [] if getBranches() return undefined', () => {
// // spyOn<any>(spectator.service, '_filter').and.returnValue([]);
// // const setBranchesSpy = spyOn(spectator.service, 'setBranches');
// // spectator.service.loadBranchesResponseFn({ response: branches });
// // expect(setBranchesSpy).toHaveBeenCalledWith([]);
// // });
it('should call setSelectedBranchId(selectedBranchId) if selectedBranch is set', () => {
const selectedBranch = { id: 123 };
const setSelectedBranchSpy = spyOn(spectator.service, 'setSelectedBranch');
spectator.service.loadBranchesResponseFn({ response: branches, selectedBranch });
expect(setSelectedBranchSpy).toHaveBeenCalledWith(selectedBranch);
});
// it('should call setSelectedBranchId(selectedBranchId) if selectedBranch is set', () => {
// const selectedBranch = { id: 123 };
// const setSelectedBranchSpy = spyOn(spectator.service, 'setSelectedBranch');
// spectator.service.loadBranchesResponseFn({ response: branches, selectedBranch });
// expect(setSelectedBranchSpy).toHaveBeenCalledWith(selectedBranch);
// });
it('should not call setSelectedBranch(selectedBranch) if selectedBranch is not set', () => {
const setSelectedBranchSpy = spyOn(spectator.service, 'setSelectedBranch');
spectator.service.loadBranchesResponseFn({ response: branches });
expect(setSelectedBranchSpy).not.toHaveBeenCalled();
});
// it('should not call setSelectedBranch(selectedBranch) if selectedBranch is not set', () => {
// const setSelectedBranchSpy = spyOn(spectator.service, 'setSelectedBranch');
// spectator.service.loadBranchesResponseFn({ response: branches });
// expect(setSelectedBranchSpy).not.toHaveBeenCalled();
// });
it('should call setFetching(false)', () => {
const setFetchingSpy = spyOn(spectator.service, 'setFetching');
spectator.service.loadBranchesResponseFn({ response: branches });
expect(setFetchingSpy).toHaveBeenCalledWith(false);
});
});
// it('should call setFetching(false)', () => {
// const setFetchingSpy = spyOn(spectator.service, 'setFetching');
// spectator.service.loadBranchesResponseFn({ response: branches });
// expect(setFetchingSpy).toHaveBeenCalledWith(false);
// });
// });
describe('loadBranchesErrorFn()', () => {
it('should call uiModalServiceMock.open with appropriate UiErrorModal data', () => {
const error = new Error('test');
spectator.service.loadBranchesErrorFn(error);
expect(uiModalServiceMock.open).toHaveBeenCalledWith({
title: 'Fehler beim Laden der Filialen',
content: UiErrorModalComponent,
data: error,
config: { showScrollbarY: false },
});
});
});
// describe('loadBranchesErrorFn()', () => {
// it('should call uiModalServiceMock.open with appropriate UiErrorModal data', () => {
// const error = new Error('test');
// spectator.service.loadBranchesErrorFn(error);
// expect(uiModalServiceMock.open).toHaveBeenCalledWith({
// title: 'Fehler beim Laden der Filialen',
// content: UiErrorModalComponent,
// data: error,
// config: { showScrollbarY: false },
// });
// });
// });
describe('setSelectedBranch()', () => {
it('should call patchState with empty query and undefined selectedBranch if function call without arguments', () => {
const patchStateSpy = spyOn(spectator.service, 'patchState');
spectator.service.setSelectedBranch();
expect(patchStateSpy).toHaveBeenCalledWith({ selectedBranch: undefined, query: '' });
});
// describe('setSelectedBranch()', () => {
// it('should call patchState with empty query and undefined selectedBranch if function call without arguments', () => {
// const patchStateSpy = spyOn(spectator.service, 'patchState');
// spectator.service.setSelectedBranch();
// expect(patchStateSpy).toHaveBeenCalledWith({ selectedBranch: undefined, query: '' });
// });
it('should call formatBranch(selectedBranch) if function call with selectedBranch', () => {
const selectedBranch = { id: 123 };
const formatBranchBySpy = spyOn(spectator.service, 'formatBranch');
spectator.service.setSelectedBranch(selectedBranch);
expect(formatBranchBySpy).toHaveBeenCalledWith(selectedBranch);
});
// it('should call formatBranch(selectedBranch) if function call with selectedBranch', () => {
// const selectedBranch = { id: 123 };
// const formatBranchBySpy = spyOn(spectator.service, 'formatBranch');
// spectator.service.setSelectedBranch(selectedBranch);
// expect(formatBranchBySpy).toHaveBeenCalledWith(selectedBranch);
// });
it('should call patchState({ selectedBranch, query: this.formatBranch(selectedBranch) }) if function call with selectedBranch', () => {
const selectedBranch = { id: 123 };
const query = 'test-branch';
spyOn(spectator.service, 'formatBranch').and.returnValue(query);
const patchStateSpy = spyOn(spectator.service, 'patchState');
spectator.service.setSelectedBranch(selectedBranch);
expect(patchStateSpy).toHaveBeenCalledWith({ selectedBranch, query });
});
});
// it('should call patchState({ selectedBranch, query: this.formatBranch(selectedBranch) }) if function call with selectedBranch', () => {
// const selectedBranch = { id: 123 };
// const query = 'test-branch';
// spyOn(spectator.service, 'formatBranch').and.returnValue(query);
// const patchStateSpy = spyOn(spectator.service, 'patchState');
// spectator.service.setSelectedBranch(selectedBranch);
// expect(patchStateSpy).toHaveBeenCalledWith({ selectedBranch, query });
// });
// });
describe('setQuery()', () => {
it('should call patchState with query', () => {
const query = 'test';
spyOn(spectator.service, 'patchState');
spectator.service.setQuery(query);
expect(spectator.service.patchState).toHaveBeenCalledWith({ query });
});
});
// describe('setQuery()', () => {
// it('should call patchState with query', () => {
// const query = 'test';
// spyOn(spectator.service, 'patchState');
// spectator.service.setQuery(query);
// expect(spectator.service.patchState).toHaveBeenCalledWith({ query });
// });
// });
describe('setBranches()', () => {
it('should call patchState with branches', () => {
const branches = [{ id: 1 }, { id: 2 }];
spyOn(spectator.service, 'patchState');
spectator.service.setBranches(branches);
expect(spectator.service.patchState).toHaveBeenCalledWith({ branches });
});
});
// describe('setBranches()', () => {
// it('should call patchState with branches', () => {
// const branches = [{ id: 1 }, { id: 2 }];
// spyOn(spectator.service, 'patchState');
// spectator.service.setBranches(branches);
// expect(spectator.service.patchState).toHaveBeenCalledWith({ branches });
// });
// });
describe('setFetching()', () => {
it('should call patchState with fetching', () => {
const fetching = true;
spyOn(spectator.service, 'patchState');
spectator.service.setFetching(fetching);
expect(spectator.service.patchState).toHaveBeenCalledWith({ fetching });
});
});
// describe('setFetching()', () => {
// it('should call patchState with fetching', () => {
// const fetching = true;
// spyOn(spectator.service, 'patchState');
// spectator.service.setFetching(fetching);
// expect(spectator.service.patchState).toHaveBeenCalledWith({ fetching });
// });
// });
describe('formatBranch()', () => {
it('should return a formatted branch with key', () => {
const branch = {
id: 1,
name: 'Test',
key: 'T',
};
const formattedString = spectator.service.formatBranch(branch);
expect(formattedString).toBe('T - Test');
});
// describe('formatBranch()', () => {
// it('should return a formatted branch with key', () => {
// const branch = {
// id: 1,
// name: 'Test',
// key: 'T',
// };
// const formattedString = spectator.service.formatBranch(branch);
// expect(formattedString).toBe('T - Test');
// });
it('should return a formatted branch without key', () => {
const branch = {
id: 1,
name: 'Test',
};
const formattedString = spectator.service.formatBranch(branch);
expect(formattedString).toBe('Test');
});
// it('should return a formatted branch without key', () => {
// const branch = {
// id: 1,
// name: 'Test',
// };
// const formattedString = spectator.service.formatBranch(branch);
// expect(formattedString).toBe('Test');
// });
it('should return an empty string if called without branch', () => {
const formattedString = spectator.service.formatBranch();
expect(formattedString).toBe('');
});
});
// it('should return an empty string if called without branch', () => {
// const formattedString = spectator.service.formatBranch();
// expect(formattedString).toBe('');
// });
// });
// describe('_filter()', () => {
// it('should return branches based on filter criterias', () => {
// const branches = [
// {
// id: 1,
// branchType: 2 as BranchType,
// },
// {
// id: 2,
// isOnline: true,
// isShippingEnabled: true,
// isOrderingEnabled: true,
// branchType: 1 as BranchType,
// },
// ];
// const branchType: BranchType = 1;
// // describe('_filter()', () => {
// // it('should return branches based on filter criterias', () => {
// // const branches = [
// // {
// // id: 1,
// // branchType: 2 as BranchType,
// // },
// // {
// // id: 2,
// // isOnline: true,
// // isShippingEnabled: true,
// // isOrderingEnabled: true,
// // branchType: 1 as BranchType,
// // },
// // ];
// // const branchType: BranchType = 1;
// expect(spectator.service['_filter']({ branches, branchType })).toEqual([branches[1]]);
// });
// });
});
// // expect(spectator.service['_filter']({ branches, branchType })).toEqual([branches[1]]);
// // });
// // });
// });

View File

@@ -2,7 +2,9 @@ import { Injectable } from '@angular/core';
import { AuthService } from '@core/auth';
import { DomainAvailabilityService } from '@domain/availability';
import { OpenStreetMap, OpenStreetMapParams, PlaceDto } from '@external/openstreetmap';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { BranchDTO, BranchType } from '@swagger/checkout';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { geoDistance, GeoLocation } from '@utils/common';

View File

@@ -14,7 +14,9 @@ import { UntypedFormControl } from '@angular/forms';
import { AuthService } from '@core/auth';
import { DomainOmsService, DomainReceiptService } from '@domain/oms';
import { HistoryModalComponent, HistoryData } from '@modal/history';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';
import { OrderDTO, OrderItemListItemDTO, ReceiptDTO, ReceiptType } from '@swagger/oms';
import { UiErrorModalComponent, UiMessageModalComponent, UiModalService } from '@ui/modal';
import { isEqual } from 'lodash';

View File

@@ -2,7 +2,6 @@ import { FocusOrigin, FocusableOption } from '@angular/cdk/a11y';
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
import { CommonModule } from '@angular/common';
import { Component, ChangeDetectionStrategy, Input, ElementRef, ViewEncapsulation, HostListener } from '@angular/core';
import { SelectComponent } from './select.component';
@Component({
selector: 'shared-select-option',
@@ -28,10 +27,7 @@ export class SelectOptionComponent<T = any> implements FocusableOption {
disabled = false;
constructor(
private _elementRef: ElementRef<HTMLElement>,
private _host: SelectComponent,
) {}
constructor(private _elementRef: ElementRef<HTMLElement>) {}
focus(origin?: FocusOrigin): void {
throw new Error('Method not implemented.');
}
@@ -40,10 +36,16 @@ export class SelectOptionComponent<T = any> implements FocusableOption {
return this._elementRef.nativeElement?.textContent?.trim();
}
private _onSelect: (value: T) => void = () => {};
registerOnSelect(fn: (value: T) => void): void {
this._onSelect = fn;
}
@HostListener('click', ['$event'])
select(event: Event): void {
event.preventDefault();
event.stopPropagation();
this._host.setValue(this.value);
this._onSelect(this.value);
}
}

View File

@@ -103,6 +103,10 @@ export class SelectComponent<T = any> extends BaseFormControlDirective implement
ngAfterContentInit() {
this.options.changes.pipe(takeUntil(this._onDestroy$)).subscribe(() => {
this.options.forEach((option) => {
option.registerOnSelect((value) => this.setValue(value));
});
this._cdr.markForCheck();
});
}

View File

@@ -1,24 +1,24 @@
import { SpectatorService, createServiceFactory } from '@ngneat/spectator';
import { GenderSettingsService } from './gender-settings.service';
import { Config } from '@core/config';
// import { SpectatorService, createServiceFactory } from '@ngneat/spectator';
// import { GenderSettingsService } from './gender-settings.service';
// import { Config } from '@core/config';
describe('GenderSettingsService', () => {
let spectator: SpectatorService<GenderSettingsService>;
// describe('GenderSettingsService', () => {
// let spectator: SpectatorService<GenderSettingsService>;
const createComponent = createServiceFactory({
service: GenderSettingsService,
mocks: [Config],
});
// const createComponent = createServiceFactory({
// service: GenderSettingsService,
// mocks: [Config],
// });
it('should create', () => {
expect(spectator.service).toBeTruthy();
});
// it('should create', () => {
// expect(spectator.service).toBeTruthy();
// });
describe('getGenderByValue()', () => {
it('should return gender based on input value', () => {});
});
// describe('getGenderByValue()', () => {
// it('should return gender based on input value', () => {});
// });
describe('_transformGendersArray()', () => {
it('should return genders array based on available genders from config', () => {});
});
});
// describe('_transformGendersArray()', () => {
// it('should return genders array based on available genders from config', () => {});
// });
// });

View File

@@ -4,7 +4,7 @@ import { Router } from '@angular/router';
import { ApplicationProcess, ApplicationService } from '@core/application';
import { BreadcrumbService } from '@core/breadcrumb';
import { DomainCheckoutService } from '@domain/checkout';
import { MessageModalService } from '@modal/message';
import { injectOpenMessageModal } from '@modal/message';
import { CustomerOrdersNavigationService, ProductCatalogNavigationService } from '@shared/services/navigation';
import { NEVER, Observable, of } from 'rxjs';
import { delay, first, map, switchMap } from 'rxjs/operators';
@@ -32,12 +32,13 @@ export class ShellProcessBarComponent implements OnInit {
trackByFn = (_: number, process: ApplicationProcess) => process.id;
openMessageModal = injectOpenMessageModal();
constructor(
private _app: ApplicationService,
private _router: Router,
private _catalogNavigationService: ProductCatalogNavigationService,
private _customerOrderNavigationService: CustomerOrdersNavigationService,
private _messageModalService: MessageModalService,
private _checkoutService: DomainCheckoutService,
private _breadcrumb: BreadcrumbService,
) {}
@@ -97,7 +98,7 @@ export class ShellProcessBarComponent implements OnInit {
async closeAllProcesses() {
const processes = await this.processes$.pipe(first()).toPromise();
this._messageModalService.open({
this.openMessageModal({
title: 'Vorgänge schließen',
message: `Sind Sie sich sicher, dass sie alle ${processes.length} Vorgänge schließen wollen?`,
actions: [

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit, inject } from '@angular/core';
import { first, map, retry } from 'rxjs/operators';
import { ShellService } from '../shell.service';
import { BehaviorSubject, Observable, combineLatest } from 'rxjs';
@@ -17,6 +17,14 @@ import { EnvironmentService } from '@core/environment';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShellTopBarComponent implements OnInit {
private _shellService = inject(ShellService);
private _stockService = inject(StockService);
private _authService = inject(AuthService);
private readonly _notificationsHub = inject(NotificationsHub);
private _modal = inject(UiModalService);
private _app = inject(ApplicationService);
private _environment = inject(EnvironmentService);
title$ = this._app.getTitle$();
menuIcon$ = this._shellService.sideMenuOpen$.pipe(map((open) => (open ? 'close' : 'menu')));
@@ -44,16 +52,6 @@ export class ShellTopBarComponent implements OnInit {
return this._environment.matchTablet$;
}
constructor(
private _shellService: ShellService,
private _stockService: StockService,
private _authService: AuthService,
private readonly _notificationsHub: NotificationsHub,
private _modal: UiModalService,
private _app: ApplicationService,
private _environment: EnvironmentService,
) {}
ngOnInit() {
this._app.getSection$().subscribe(this.sectionSubject);
}

View File

@@ -0,0 +1,5 @@
{
"rules": {
"@typescript-eslint/consistent-type-imports": ["error", { "disallowTypeAnnotations": false }]
}
}

View File

@@ -0,0 +1,369 @@
import { Meta } from '@storybook/blocks';
import Github from './assets/github.svg';
import Discord from './assets/discord.svg';
import Youtube from './assets/youtube.svg';
import Tutorials from './assets/tutorials.svg';
import Styling from './assets/styling.png';
import Context from './assets/context.png';
import Assets from './assets/assets.png';
import Docs from './assets/docs.png';
import Share from './assets/share.png';
import FigmaPlugin from './assets/figma-plugin.png';
import Testing from './assets/testing.png';
import Accessibility from './assets/accessibility.png';
import Theming from './assets/theming.png';
import AddonLibrary from './assets/addon-library.png';
export const RightArrow = () => (
<svg
viewBox="0 0 14 14"
width="8px"
height="14px"
style={{
marginLeft: '4px',
display: 'inline-block',
shapeRendering: 'inherit',
verticalAlign: 'middle',
fill: 'currentColor',
'path fill': 'currentColor',
}}
>
<path d="m11.1 7.35-5.5 5.5a.5.5 0 0 1-.7-.7L10.04 7 4.9 1.85a.5.5 0 1 1 .7-.7l5.5 5.5c.2.2.2.5 0 .7Z" />
</svg>
);
<Meta title="Configure your project" />
<div className="sb-container">
<div className='sb-section-title'>
# Configure your project
Because Storybook works separately from your app, you'll need to configure it for your specific stack and setup. Below, explore guides for configuring Storybook with popular frameworks and tools. If you get stuck, learn how you can ask for help from our community.
</div>
<div className="sb-section">
<div className="sb-section-item">
<img
src={Styling}
alt="A wall of logos representing different styling technologies"
/>
<h4 className="sb-section-item-heading">Add styling and CSS</h4>
<p className="sb-section-item-paragraph">Like with web applications, there are many ways to include CSS within Storybook. Learn more about setting up styling within Storybook.</p>
<a
href="https://storybook.js.org/docs/configure/styling-and-css/?renderer=angular"
target="_blank"
>Learn more<RightArrow /></a>
</div>
<div className="sb-section-item">
<img
src={Context}
alt="An abstraction representing the composition of data for a component"
/>
<h4 className="sb-section-item-heading">Provide context and mocking</h4>
<p className="sb-section-item-paragraph">Often when a story doesn't render, it's because your component is expecting a specific environment or context (like a theme provider) to be available.</p>
<a
href="https://storybook.js.org/docs/writing-stories/decorators/?renderer=angular#context-for-mocking"
target="_blank"
>Learn more<RightArrow /></a>
</div>
<div className="sb-section-item">
<img src={Assets} alt="A representation of typography and image assets" />
<div>
<h4 className="sb-section-item-heading">Load assets and resources</h4>
<p className="sb-section-item-paragraph">To link static files (like fonts) to your projects and stories, use the
`staticDirs` configuration option to specify folders to load when
starting Storybook.</p>
<a
href="https://storybook.js.org/docs/configure/images-and-assets/?renderer=angular"
target="_blank"
>Learn more<RightArrow /></a>
</div>
</div>
</div>
</div>
<div className="sb-container">
<div className='sb-section-title'>
# Do more with Storybook
Now that you know the basics, let's explore other parts of Storybook that will improve your experience. This list is just to get you started. You can customise Storybook in many ways to fit your needs.
</div>
<div className="sb-section">
<div className="sb-features-grid">
<div className="sb-grid-item">
<img src={Docs} alt="A screenshot showing the autodocs tag being set, pointing a docs page being generated" />
<h4 className="sb-section-item-heading">Autodocs</h4>
<p className="sb-section-item-paragraph">Auto-generate living,
interactive reference documentation from your components and stories.</p>
<a
href="https://storybook.js.org/docs/writing-docs/autodocs/?renderer=angular"
target="_blank"
>Learn more<RightArrow /></a>
</div>
<div className="sb-grid-item">
<img src={Share} alt="A browser window showing a Storybook being published to a chromatic.com URL" />
<h4 className="sb-section-item-heading">Publish to Chromatic</h4>
<p className="sb-section-item-paragraph">Publish your Storybook to review and collaborate with your entire team.</p>
<a
href="https://storybook.js.org/docs/sharing/publish-storybook/?renderer=angular#publish-storybook-with-chromatic"
target="_blank"
>Learn more<RightArrow /></a>
</div>
<div className="sb-grid-item">
<img src={FigmaPlugin} alt="Windows showing the Storybook plugin in Figma" />
<h4 className="sb-section-item-heading">Figma Plugin</h4>
<p className="sb-section-item-paragraph">Embed your stories into Figma to cross-reference the design and live
implementation in one place.</p>
<a
href="https://storybook.js.org/docs/sharing/design-integrations/?renderer=angular#embed-storybook-in-figma-with-the-plugin"
target="_blank"
>Learn more<RightArrow /></a>
</div>
<div className="sb-grid-item">
<img src={Testing} alt="Screenshot of tests passing and failing" />
<h4 className="sb-section-item-heading">Testing</h4>
<p className="sb-section-item-paragraph">Use stories to test a component in all its variations, no matter how
complex.</p>
<a
href="https://storybook.js.org/docs/writing-tests/?renderer=angular"
target="_blank"
>Learn more<RightArrow /></a>
</div>
<div className="sb-grid-item">
<img src={Accessibility} alt="Screenshot of accessibility tests passing and failing" />
<h4 className="sb-section-item-heading">Accessibility</h4>
<p className="sb-section-item-paragraph">Automatically test your components for a11y issues as you develop.</p>
<a
href="https://storybook.js.org/docs/writing-tests/accessibility-testing/?renderer=angular"
target="_blank"
>Learn more<RightArrow /></a>
</div>
<div className="sb-grid-item">
<img src={Theming} alt="Screenshot of Storybook in light and dark mode" />
<h4 className="sb-section-item-heading">Theming</h4>
<p className="sb-section-item-paragraph">Theme Storybook's UI to personalize it to your project.</p>
<a
href="https://storybook.js.org/docs/configure/theming/?renderer=angular"
target="_blank"
>Learn more<RightArrow /></a>
</div>
</div>
</div>
</div>
<div className='sb-addon'>
<div className='sb-addon-text'>
<h4>Addons</h4>
<p className="sb-section-item-paragraph">Integrate your tools with Storybook to connect workflows.</p>
<a
href="https://storybook.js.org/addons/"
target="_blank"
>Discover all addons<RightArrow /></a>
</div>
<div className='sb-addon-img'>
<img src={AddonLibrary} alt="Integrate your tools with Storybook to connect workflows." />
</div>
</div>
<div className="sb-section sb-socials">
<div className="sb-section-item">
<img src={Github} alt="Github logo" className="sb-explore-image"/>
Join our contributors building the future of UI development.
<a
href="https://github.com/storybookjs/storybook"
target="_blank"
>Star on GitHub<RightArrow /></a>
</div>
<div className="sb-section-item">
<img src={Discord} alt="Discord logo" className="sb-explore-image"/>
<div>
Get support and chat with frontend developers.
<a
href="https://discord.gg/storybook"
target="_blank"
>Join Discord server<RightArrow /></a>
</div>
</div>
<div className="sb-section-item">
<img src={Youtube} alt="Youtube logo" className="sb-explore-image"/>
<div>
Watch tutorials, feature previews and interviews.
<a
href="https://www.youtube.com/@chromaticui"
target="_blank"
>Watch on YouTube<RightArrow /></a>
</div>
</div>
<div className="sb-section-item">
<img src={Tutorials} alt="A book" className="sb-explore-image"/>
<p>Follow guided walkthroughs on for key workflows.</p>
<a
href="https://storybook.js.org/tutorials/"
target="_blank"
>Discover tutorials<RightArrow /></a>
</div>
</div>
<style>
{`
.sb-container {
margin-bottom: 48px;
}
.sb-section {
width: 100%;
display: flex;
flex-direction: row;
gap: 20px;
}
img {
object-fit: cover;
}
.sb-section-title {
margin-bottom: 32px;
}
.sb-section a:not(h1 a, h2 a, h3 a) {
font-size: 14px;
}
.sb-section-item, .sb-grid-item {
flex: 1;
display: flex;
flex-direction: column;
}
.sb-section-item-heading {
padding-top: 20px !important;
padding-bottom: 5px !important;
margin: 0 !important;
}
.sb-section-item-paragraph {
margin: 0;
padding-bottom: 10px;
}
.sb-chevron {
margin-left: 5px;
}
.sb-features-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 32px 20px;
}
.sb-socials {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.sb-socials p {
margin-bottom: 10px;
}
.sb-explore-image {
max-height: 32px;
align-self: flex-start;
}
.sb-addon {
width: 100%;
display: flex;
align-items: center;
position: relative;
background-color: #EEF3F8;
border-radius: 5px;
border: 1px solid rgba(0, 0, 0, 0.05);
background: #EEF3F8;
height: 180px;
margin-bottom: 48px;
overflow: hidden;
}
.sb-addon-text {
padding-left: 48px;
max-width: 240px;
}
.sb-addon-text h4 {
padding-top: 0px;
}
.sb-addon-img {
position: absolute;
left: 345px;
top: 0;
height: 100%;
width: 200%;
overflow: hidden;
}
.sb-addon-img img {
width: 650px;
transform: rotate(-15deg);
margin-left: 40px;
margin-top: -72px;
box-shadow: 0 0 1px rgba(255, 255, 255, 0);
backface-visibility: hidden;
}
@media screen and (max-width: 800px) {
.sb-addon-img {
left: 300px;
}
}
@media screen and (max-width: 600px) {
.sb-section {
flex-direction: column;
}
.sb-features-grid {
grid-template-columns: repeat(1, 1fr);
}
.sb-socials {
grid-template-columns: repeat(2, 1fr);
}
.sb-addon {
height: 280px;
align-items: flex-start;
padding-top: 32px;
overflow: hidden;
}
.sb-addon-text {
padding-left: 24px;
}
.sb-addon-img {
right: 0;
left: 0;
top: 130px;
bottom: 0;
overflow: hidden;
height: auto;
width: 124%;
}
.sb-addon-img img {
width: 1200px;
transform: rotate(-12deg);
margin-left: 0;
margin-top: 48px;
margin-bottom: -40px;
margin-left: -24px;
}
}
`}
</style>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Some files were not shown because too many files have changed in this diff Show More