Compare commits

...

46 Commits

Author SHA1 Message Date
Michael Auer
0ac34740bb Merge branch 'hotfix/traefik-ingressroute-with-path' 2025-03-11 18:05:31 +01:00
Michael Auer
591824196b Cherry-Pick: PR 1824: ISA-Frontend - Expliziter Pfad für Traefik IngressRoute
(cherry picked from commit c9b2762bbc)
2025-02-28 11:15:20 +01:00
Lorenz Hilpert
1847c6944e Merge branch 'release/3.4' 2025-02-10 10:41:14 +01:00
Lorenz Hilpert
f743ce59fa #4922 Rename customer_name to customer_no in goods service and pickup shelf service
(cherry picked from commit ca998c0685)
2025-01-15 11:28:56 +01:00
Lorenz Hilpert
99feb499a2 Update Scandit licence key for staging environment 2025-01-02 13:41:02 +01:00
Lorenz Hilpert
bb5b6e2e59 Update Scandit licence key for staging environment 2024-12-05 16:35:45 +01:00
Lorenz Hilpert
f57988f83e Update Scandit Licence Key for production 2024-12-05 15:38:24 +01:00
Lorenz Hilpert
17a68b9dbb Merged PR 1823: #4895 - Add download availability to article details component and update pri...
#4895 - Add download availability to article details component and update price mapping logic
2024-11-28 16:49:28 +00:00
Nino Righi
a0c8035dbb Merged PR 1820: Fix - Close dropdown after selecting a reason in add product modal
Fix - Close dropdown after selecting a reason in add product modal
2024-11-27 14:21:12 +00:00
Nino Righi
34e96f0751 Merged PR 1821: Refactor getCachedData method to be asynchronous and improve cache handling
Refactor getCachedData method to be asynchronous and improve cache handling
2024-11-27 14:20:25 +00:00
Lorenz Hilpert
9ba05253e9 Enhance select component to register options on initialization and remove debug log 2024-11-27 11:52:02 +01:00
Lorenz Hilpert
98a9346c1a Refactor customer number handling and add combined observable for customer number and selected order item changes 2024-11-27 11:43:49 +01:00
Lorenz Hilpert
fa66d2389a Improvements - Um Cover Items die nicht zur ausgeäjlten bestellung gehören zu filtern 2024-11-26 17:02:57 +01:00
Lorenz Hilpert
6743c8e630 Fix #4891 Kundendaten erfassen // Land bei Lieferung nicht auswählbar 2024-11-26 16:56:50 +01:00
Lorenz Hilpert
f62e198aed Fix - Nachbestellen - Dropdown wird nun nach der Auswahl geschlossen und Button Bestellen ist wieder klickbar 2024-11-26 16:34:32 +01:00
Nino
387e6b08ed Remove unused selectedCompartmentInfo properties from PickupShelfOutDetailsComponent 2024-11-25 17:31:49 +01:00
Lorenz Hilpert
721fd06c76 Remove console logs from beforeFetchCoverOrderItems and fetchCoverOrderItemsDone methods in PickupShelfDetailsStore 2024-11-25 16:51:43 +01:00
Lorenz Hilpert
0fcdb308b5 Remove Scandit overlay component and enhance error handling in ScanditScanAdapter; add logging for order item fetching in PickupShelfDetailsStore and list components 2024-11-25 16:50:15 +01:00
Lorenz Hilpert
5492329a21 Merge branch 'master' into release/3.4 2024-11-25 16:26:54 +01:00
Nino
f97253e82a Refactor distinctUntilChanged to use a custom equality check in pickup-shelf-details.store.ts 2024-11-25 15:31:24 +01:00
Nino
b926efb635 #4885 Compartment Info Bugfix 2024-11-25 15:23:36 +01:00
Lorenz Hilpert
cdc2553d73 Merge branch 'hotfix/scandit-package-replacement' 2024-11-25 13:56:08 +01:00
Lorenz Hilpert
8781c50e34 Merge branch 'master' into release/3.4 2024-11-25 13:50:34 +01:00
Lorenz Hilpert
05eb3cc756 Revert "Refactor ScanditOverlayComponent to use dependency injection for DataCaptureContext and DataCaptureView, and enhance module setup with async context initialization"
This reverts commit 6e1c434edf.
2024-11-22 18:31:05 +01:00
Lorenz Hilpert
6e1c434edf Refactor ScanditOverlayComponent to use dependency injection for DataCaptureContext and DataCaptureView, and enhance module setup with async context initialization 2024-11-22 18:23:05 +01:00
Lorenz Hilpert
ed8e937924 Update Scandit license keys across configuration files 2024-11-22 17:26:27 +01:00
Lorenz Hilpert
1bd17fd887 Update Scandit integration to use new SDK, adjust TypeScript configuration, and refine overlay component styles 2024-11-22 16:19:32 +01:00
Lorenz Hilpert
8900a77d7a Enhance PickupShelfInDetailsComponent with signals for order items and optimize fetching logic 2024-11-19 16:27:18 +01:00
Lorenz Hilpert
4b10dd96d9 Merge branch 'hotfix/abholfach-zubuchen-und-cover-items' 2024-11-19 13:50:36 +01:00
Lorenz Hilpert
1126e4f0c1 Import tapResponse alongside ComponentStore in pickup-shelf-details.store.ts 2024-11-19 13:50:15 +01:00
Lorenz Hilpert
e9f24a88d6 Refactor PickupShelfInDetailsComponent to use signals for customer number and update fetch logic 2024-11-19 13:48:33 +01:00
Lorenz Hilpert
cb6779fc83 Bump minor version from 3 to 4 in Azure Pipelines configuration 2024-11-12 17:14:19 +01:00
Lorenz Hilpert
f2c95b6a16 Merge tag '3.3' into develop
Merge branch release/3.3 3.3
2024-11-12 17:05:47 +01:00
Lorenz Hilpert
d48680c59e Merge branch 'release/3.3' 2024-11-12 17:04:15 +01:00
Lorenz Hilpert
775390b5df Add dynamic IDs to filter buttons in filter group component 2024-11-05 13:18:21 +01:00
Lorenz Hilpert
1788f566e3 Add filter buttons with unique IDs in package result component 2024-11-05 11:05:47 +01:00
Nino Righi
d4e1088190 Merged PR 1818: #4836 Small Bugfix
#4836 Small Bugfix
2024-10-31 17:07:26 +00:00
Lorenz Hilpert
a8ecd1f07b Merged PR 1817: Enhance error handling and state management in app module and root state service
Enhance error handling and state management in app module and root state service

Related work items: #4835
2024-10-30 12:14:58 +00:00
Lorenz Hilpert
2c239ac597 Merge branch 'develop' of ssh.dev.azure.com:v3/hugendubel/ISA/ISA-Frontend into develop 2024-10-30 11:47:07 +01:00
Lorenz Hilpert
200eb7f217 Mark NativeScanAdapter and native-container.service as deprecated 2024-10-30 11:46:14 +01:00
Nino Righi
694fc6d084 Merged PR 1816: #4836 Fix Printer Handling on Small Amount Invoice
#4836 Fix Printer Handling on Small Amount Invoice
2024-10-30 10:39:53 +00:00
Lorenz Hilpert
8ae990bcde Merged PR 1815: Angular Update V18
Related work items: #4830, #4834
2024-10-22 09:23:23 +00:00
Lorenz Hilpert
1d472ce3df (cherry picked from commit 4c027922283bc4113253310c9d47e7c8944427a3) 2024-10-07 19:04:31 +02:00
Nino Righi
1d19779dac Merged PR 1805: #4687 Hotfix Organisation Name Update Order
#4687 Hotfix Organisation Name Update Order
2024-10-07 14:33:04 +00:00
Nino
90e671d285 #4687 Changes to View, Added Organisation Input Field 2024-10-07 12:07:28 +02:00
Lorenz Hilpert
33fb44f20a Upgrade Version to 3.3 2024-09-24 16:51:36 +02:00
1060 changed files with 394343 additions and 21949 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

@@ -27,8 +27,7 @@
"pdfjs-dist/build/pdf",
"pdfjs-dist/web/pdf_viewer",
"pdfjs-dist/es5/build/pdf",
"pdfjs-dist/es5/web/pdf_viewer",
"scandit-sdk"
"pdfjs-dist/es5/web/pdf_viewer"
],
"outputPath": "dist/isa-app",
"index": "apps/isa-app/src/index.html",
@@ -44,7 +43,7 @@
"apps/isa-app/src/manifest.webmanifest",
{
"glob": "**/*",
"input": "node_modules/scandit-sdk/build",
"input": "node_modules/scandit-web-datacapture-barcode/build/engine",
"output": "scandit"
}
],
@@ -125,6 +124,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

@@ -4,6 +4,10 @@ import { Observable } from 'rxjs';
import { filter, map, take } from 'rxjs/operators';
import { ScanAdapter } from './scan-adapter';
/**
* @deprecated This service will be removed in future versions.
* Please use the new ScanService instead.
*/
@Injectable()
export class NativeScanAdapter implements ScanAdapter {
readonly name = 'Native';

View File

@@ -3,12 +3,15 @@
}
.scanner-container {
width: 100vw;
/* width: 100vw;
height: 100vh;
max-width: 100vh;
max-height: 100vh; */
}
.close-scanner {
@apply absolute bottom-12 left-[50%] -translate-x-[50%] block px-6 py-4 bg-white text-brand border-2 border-solid border-brand rounded-full text-lg font-bold mx-auto mt-4;
@apply whitespace-nowrap;
}
@screen desktop {

View File

@@ -1,6 +1,6 @@
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy } from '@angular/core';
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
import { Barcode, BarcodePicker, ScanResult, ScanSettings } from 'scandit-sdk';
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy, OnInit } from '@angular/core';
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';
@Component({
selector: 'app-scandit-overlay',
@@ -8,8 +8,11 @@ import { Barcode, BarcodePicker, ScanResult, ScanSettings } from 'scandit-sdk';
styleUrls: ['scandit-overlay.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
private _barcodePicker: BarcodePicker;
export class ScanditOverlayComponent implements OnInit, AfterViewInit, OnDestroy {
private dataCaptureContext: DataCaptureContext;
private dataCaptureView: DataCaptureView;
private barcodeCapture: BarcodeCapture;
private camera: Camera;
private _onScan?: (code: string) => void;
@@ -17,57 +20,58 @@ export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
@ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;
constructor(
private _zone: NgZone,
private _modal: UiModalService,
) {}
constructor(private _zone: NgZone) {}
ngAfterViewInit(): void {
this.createBarcodePicker()
.then(() => {
this._barcodePicker.on('scan', (scanResult) => {
this._zone.run(() => this.handleScanrResult(scanResult));
ngOnInit(): void {
this.dataCaptureView = new DataCaptureView();
this.dataCaptureView.connectToElement(this.scanContainer.nativeElement);
this.dataCaptureView.showProgressBar();
}
async ngAfterViewInit() {
this.dataCaptureContext = await DataCaptureContext.create();
this.dataCaptureView.setContext(this.dataCaptureContext);
this.barcodeCapture = await BarcodeCapture.forContext(this.dataCaptureContext, this.getScanSettings());
this.barcodeCapture.addListener({
didScan: (_, session, __) => {
this._zone.run(() => {
const result = session.newlyRecognizedBarcode;
const code = result?.data ?? '';
this._onScan?.(code);
});
})
.catch((err: Error) => {
this._modal
.open({
content: UiMessageModalComponent,
title: 'Zugriff auf Kamera verweigert',
data: { message: 'Falls Sie den Zugriff erlauben möchten, können Sie das über die Webseiteinstellung Ihres Browsers.' },
})
.afterClosed$.subscribe(() => {
this._onClose?.();
});
});
}
async createBarcodePicker() {
this._barcodePicker = await BarcodePicker.create(this.scanContainer.nativeElement, {
playSoundOnScan: true,
vibrateOnScan: true,
},
});
this._barcodePicker.applyScanSettings(this.getScanSettings());
this.camera = Camera.default;
this.dataCaptureContext.setFrameSource(this.camera);
await this.camera.switchToDesiredState(FrameSourceState.On);
this.dataCaptureView.hideProgressBar();
}
getScanSettings(): ScanSettings {
return new ScanSettings({
blurryRecognition: false,
getScanSettings(): BarcodeCaptureSettings {
const settings = new BarcodeCaptureSettings();
enabledSymbologies: [
Barcode.Symbology.EAN8,
Barcode.Symbology.EAN13,
Barcode.Symbology.UPCA,
Barcode.Symbology.UPCE,
Barcode.Symbology.CODE128,
Barcode.Symbology.CODE39,
Barcode.Symbology.CODE93,
Barcode.Symbology.INTERLEAVED_2_OF_5,
Barcode.Symbology.QR,
],
codeDuplicateFilter: 1000,
});
settings.enableSymbologies([
Symbology.EAN8,
Symbology.EAN13UPCA,
Symbology.UPCE,
Symbology.Code128,
Symbology.Code39,
Symbology.Code93,
Symbology.InterleavedTwoOfFive,
Symbology.QR,
]);
return settings;
}
onScan(fn: (code: string) => void) {
@@ -78,26 +82,14 @@ export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
this._onClose = fn;
}
handleScanrResult(scanRestul: ScanResult) {
let result: string | undefined;
if (scanRestul.barcodes.length) {
result = scanRestul.barcodes[0].data;
} else if (scanRestul.texts.length) {
result = scanRestul.texts[0].value;
}
if (result) {
this._onScan?.(result);
}
}
close() {
this._onClose?.();
}
ngOnDestroy(): void {
this._zone.runOutsideAngular(() => {
this._barcodePicker?.destroy(true);
this.barcodeCapture?.setEnabled(false);
this.camera?.switchToDesiredState(FrameSourceState.Off);
});
}
}

View File

@@ -3,7 +3,9 @@ import { Observable, Subscriber } from 'rxjs';
import { ScanAdapter } from '../scan-adapter';
import { Overlay } from '@angular/cdk/overlay';
import { configure } from 'scandit-sdk';
import { configure } from 'scandit-web-datacapture-core';
import { barcodeCaptureLoader } from 'scandit-web-datacapture-barcode';
// import { ScanditModalComponent } from './scandit-modal';
import { Config } from '@core/config';
import { ComponentPortal } from '@angular/cdk/portal';
@@ -26,11 +28,17 @@ export class ScanditScanAdapter implements ScanAdapter {
async init(): Promise<boolean> {
if (this._environmentService.isTablet()) {
await configure(this._config.get('licence.scandit'), {
engineLocation: '/scandit/',
});
try {
await configure({
licenseKey: this._config.get('licence.scandit'),
libraryLocation: new URL('scandit', document.baseURI).toString(),
moduleLoaders: [barcodeCaptureLoader()],
});
return true;
return true;
} catch (error) {
console.error('ScanditScanAdapter.init', error);
}
}
return false;

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';
@@ -83,13 +83,13 @@ export function _appInitializerFactory(
statusElement.innerHTML = 'Native Container wird initialisiert...';
await nativeContainer.init();
statusElement.innerHTML = 'Scanner wird initialisiert...';
await scanAdapter.init();
} catch (error) {
laoderElement.remove();
statusElement.classList.add('text-xl');
statusElement.innerHTML = '<b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
statusElement.innerHTML +=
'⚡<br><br><b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
const reload = document.createElement('button');
reload.classList.add('bg-brand', 'text-white', 'p-2', 'rounded', 'cursor-pointer');
@@ -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

@@ -7,6 +7,7 @@ import { RootState } from './root.state';
import packageInfo from 'packageJson';
import { environment } from '../../environments/environment';
import { Subject } from 'rxjs';
import { AuthService } from '@core/auth';
@Injectable({ providedIn: 'root' })
export class RootStateService {
@@ -15,6 +16,7 @@ export class RootStateService {
private _cancelSave = new Subject<void>();
constructor(
private readonly _authService: AuthService,
private readonly _userStateService: UserStateService,
private _logger: Logger,
private _store: Store,
@@ -41,7 +43,7 @@ export class RootStateService {
takeUntil(this._cancelSave),
debounceTime(1000),
switchMap((state) => {
const raw = JSON.stringify({ ...state, version: packageInfo.version });
const raw = JSON.stringify({ ...state, version: packageInfo.version, sub: this._authService.getClaimByKey('sub') });
RootStateService.SaveToLocalStorageRaw(raw);
return this._userStateService.UserStateSetUserState({ content: raw });
}),
@@ -96,7 +98,12 @@ export class RootStateService {
static LoadFromLocalStorage(): RootState {
const raw = RootStateService.LoadFromLocalStorageRaw();
if (raw) {
return JSON.parse(raw);
try {
return JSON.parse(raw);
} catch (error) {
console.error('Error parsing local storage:', error);
this.RemoveFromLocalStorage();
}
}
return undefined;
}

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

@@ -73,7 +73,7 @@
},
"checkForUpdates": 3600000,
"licence": {
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
"scandit": "ApI1Sg5/KzWICPhn0CbflI4cjgXiFkKnhgEmUvAt0D3CWsck0SCIm557hJvGTqXD0A1mt3IvEwA8eQ1CBXL3EoA9lASWUcLt+FSWP9gHao+LT6Oz9QMrsJoJRC/OboodKS4/F+ZVa02eUT53X0GX9jJeEnh8EerqZimrl6oDjNLvHCzBnxtmsMZidAUaErqK5yaQQCkUKcfTQhRzVhqvsjdENR76EmrrvCSr93oMCnnDHjcyOz8O3stcNrCOGbxwDBIMwf05CzoEBhxF9SoT/fwvfWa9BRvlMTxl9lUUE2f3Aw9+0CBG7PYgZ9XGCiCM2Wy9T5cf0C5MOLr2MAIgQrlDua0oEtmC5FjFojQHJEITRmLyQnAyUU8Y+jkUUCtQNmweZKtTQT9le+G9QCzRoSsmVsVxCKxII3+8iLA+Lh9meI/vJSaQ2VpDgZVrV1Vc4V/z0Exu7Ap7R0MpzCy4hhRzdpWgf4OG815ZctwMvM7qfBqykG98B9oP3YC/LG+cpVK4Ipx5VnWBUIwVHDiocHhMjyroTBAeH3BfeCdOEpKwNK9vOxrbvUpqAc8ZOaaal08hWgFVFR8BQN+rEkiqKx5fONRXefkkyUWMdqwvoBn7ZzCr+F9GmD52Q7ZuDcyAigm2ArwDipT9QUH7gxphogcKRNAWAyaENWWKRBFWmeNYXJOuGXLr05Zye7joGFbJHxPYyUJ6KMombmYlI2GHc4JQGJNneDuL93v8AkYcfM2WfOjf0hm+SVw0TP95bD1xJwSCoKO5L6FxqMu5GPcOqik3sjGHg6XsEr10m7jt7G2PfNTgS3ft+TP32OjeSu9M80Fu3nmeqLM4a4lx9fFbGMpWDEU9wdftmPByeW7KoXyS2bkd1Mg9UP8ci0nKo2d/ThPn+iMEjXSibNeIGibaIT4ys3pjDLW2mx0IxQpwnuQfZzAHBszpMkwKuG4+FrqXff9+bZGuRQlVwhm2v5xbKRjgi99i14QkuNVUkePxllLZGFgQH0DjsLINZb+R9stBYjQmMGc2kkJfyhHx2/zvT2D2mpgcaq0ZRKco2CqDiLUJoHwLPse/fu4PWvqSKVpwiqhCehuloWTE3jkFUncwDI50hPvrfCx92cOJUE8RTsQgDoAh7JKsPHctSZfUicZyLHOuHMhtIoxs6l/lzFowbhZob/Uo7aRsipOcP/iZgEPnMEu/obXcLR3QrlQ+WuEppU4g2MZ9+xENLCqVDLEHiz+jZIvl42ePc4Ip4lJ5RQFcSSR1yYb+z/4KB/3bc308PHnEMEB5TYvVpK7M3kg2CTjos5lh733qQKwqYamgFjpr5oPUxRYwRvj41GYpcLN3Tr4WOi4lfevR5eVFBu1Jc9baY8JIOvcCL5WhXsEemnx5dUhcnP2ozloFCvU1IS60KHkXtF4NJl89tu5EECquTN5Lf9cvtIhlbmPsVg=="
},
"gender": {
"0": "Keine Anrede",

View File

@@ -72,7 +72,7 @@
},
"checkForUpdates": 900000,
"licence": {
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
"scandit": "ApI1Sg5/KzWICPhn0CbflI4cjgXiFkKnhgEmUvAt0D3CWsck0SCIm557hJvGTqXD0A1mt3IvEwA8eQ1CBXL3EoA9lASWUcLt+FSWP9gHao+LT6Oz9QMrsJoJRC/OboodKS4/F+ZVa02eUT53X0GX9jJeEnh8EerqZimrl6oDjNLvHCzBnxtmsMZidAUaErqK5yaQQCkUKcfTQhRzVhqvsjdENR76EmrrvCSr93oMCnnDHjcyOz8O3stcNrCOGbxwDBIMwf05CzoEBhxF9SoT/fwvfWa9BRvlMTxl9lUUE2f3Aw9+0CBG7PYgZ9XGCiCM2Wy9T5cf0C5MOLr2MAIgQrlDua0oEtmC5FjFojQHJEITRmLyQnAyUU8Y+jkUUCtQNmweZKtTQT9le+G9QCzRoSsmVsVxCKxII3+8iLA+Lh9meI/vJSaQ2VpDgZVrV1Vc4V/z0Exu7Ap7R0MpzCy4hhRzdpWgf4OG815ZctwMvM7qfBqykG98B9oP3YC/LG+cpVK4Ipx5VnWBUIwVHDiocHhMjyroTBAeH3BfeCdOEpKwNK9vOxrbvUpqAc8ZOaaal08hWgFVFR8BQN+rEkiqKx5fONRXefkkyUWMdqwvoBn7ZzCr+F9GmD52Q7ZuDcyAigm2ArwDipT9QUH7gxphogcKRNAWAyaENWWKRBFWmeNYXJOuGXLr05Zye7joGFbJHxPYyUJ6KMombmYlI2GHc4JQGJNneDuL93v8AkYcfM2WfOjf0hm+SVw0TP95bD1xJwSCoKO5L6FxqMu5GPcOqik3sjGHg6XsEr10m7jt7G2PfNTgS3ft+TP32OjeSu9M80Fu3nmeqLM4a4lx9fFbGMpWDEU9wdftmPByeW7KoXyS2bkd1Mg9UP8ci0nKo2d/ThPn+iMEjXSibNeIGibaIT4ys3pjDLW2mx0IxQpwnuQfZzAHBszpMkwKuG4+FrqXff9+bZGuRQlVwhm2v5xbKRjgi99i14QkuNVUkePxllLZGFgQH0DjsLINZb+R9stBYjQmMGc2kkJfyhHx2/zvT2D2mpgcaq0ZRKco2CqDiLUJoHwLPse/fu4PWvqSKVpwiqhCehuloWTE3jkFUncwDI50hPvrfCx92cOJUE8RTsQgDoAh7JKsPHctSZfUicZyLHOuHMhtIoxs6l/lzFowbhZob/Uo7aRsipOcP/iZgEPnMEu/obXcLR3QrlQ+WuEppU4g2MZ9+xENLCqVDLEHiz+jZIvl42ePc4Ip4lJ5RQFcSSR1yYb+z/4KB/3bc308PHnEMEB5TYvVpK7M3kg2CTjos5lh733qQKwqYamgFjpr5oPUxRYwRvj41GYpcLN3Tr4WOi4lfevR5eVFBu1Jc9baY8JIOvcCL5WhXsEemnx5dUhcnP2ozloFCvU1IS60KHkXtF4NJl89tu5EECquTN5Lf9cvtIhlbmPsVg=="
},
"gender": {
"0": "Keine Anrede",

View File

@@ -74,7 +74,7 @@
},
"checkForUpdates": 3600000,
"licence": {
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
"scandit": "ApI1Sg5/KzWICPhn0CbflI4cjgXiFkKnhgEmUvAt0D3CWsck0SCIm557hJvGTqXD0A1mt3IvEwA8eQ1CBXL3EoA9lASWUcLt+FSWP9gHao+LT6Oz9QMrsJoJRC/OboodKS4/F+ZVa02eUT53X0GX9jJeEnh8EerqZimrl6oDjNLvHCzBnxtmsMZidAUaErqK5yaQQCkUKcfTQhRzVhqvsjdENR76EmrrvCSr93oMCnnDHjcyOz8O3stcNrCOGbxwDBIMwf05CzoEBhxF9SoT/fwvfWa9BRvlMTxl9lUUE2f3Aw9+0CBG7PYgZ9XGCiCM2Wy9T5cf0C5MOLr2MAIgQrlDua0oEtmC5FjFojQHJEITRmLyQnAyUU8Y+jkUUCtQNmweZKtTQT9le+G9QCzRoSsmVsVxCKxII3+8iLA+Lh9meI/vJSaQ2VpDgZVrV1Vc4V/z0Exu7Ap7R0MpzCy4hhRzdpWgf4OG815ZctwMvM7qfBqykG98B9oP3YC/LG+cpVK4Ipx5VnWBUIwVHDiocHhMjyroTBAeH3BfeCdOEpKwNK9vOxrbvUpqAc8ZOaaal08hWgFVFR8BQN+rEkiqKx5fONRXefkkyUWMdqwvoBn7ZzCr+F9GmD52Q7ZuDcyAigm2ArwDipT9QUH7gxphogcKRNAWAyaENWWKRBFWmeNYXJOuGXLr05Zye7joGFbJHxPYyUJ6KMombmYlI2GHc4JQGJNneDuL93v8AkYcfM2WfOjf0hm+SVw0TP95bD1xJwSCoKO5L6FxqMu5GPcOqik3sjGHg6XsEr10m7jt7G2PfNTgS3ft+TP32OjeSu9M80Fu3nmeqLM4a4lx9fFbGMpWDEU9wdftmPByeW7KoXyS2bkd1Mg9UP8ci0nKo2d/ThPn+iMEjXSibNeIGibaIT4ys3pjDLW2mx0IxQpwnuQfZzAHBszpMkwKuG4+FrqXff9+bZGuRQlVwhm2v5xbKRjgi99i14QkuNVUkePxllLZGFgQH0DjsLINZb+R9stBYjQmMGc2kkJfyhHx2/zvT2D2mpgcaq0ZRKco2CqDiLUJoHwLPse/fu4PWvqSKVpwiqhCehuloWTE3jkFUncwDI50hPvrfCx92cOJUE8RTsQgDoAh7JKsPHctSZfUicZyLHOuHMhtIoxs6l/lzFowbhZob/Uo7aRsipOcP/iZgEPnMEu/obXcLR3QrlQ+WuEppU4g2MZ9+xENLCqVDLEHiz+jZIvl42ePc4Ip4lJ5RQFcSSR1yYb+z/4KB/3bc308PHnEMEB5TYvVpK7M3kg2CTjos5lh733qQKwqYamgFjpr5oPUxRYwRvj41GYpcLN3Tr4WOi4lfevR5eVFBu1Jc9baY8JIOvcCL5WhXsEemnx5dUhcnP2ozloFCvU1IS60KHkXtF4NJl89tu5EECquTN5Lf9cvtIhlbmPsVg=="
},
"gender": {
"0": "Keine Anrede",

View File

@@ -73,7 +73,7 @@
},
"checkForUpdates": 3600000,
"licence": {
"scandit": "AZ70hgtZLmFWHbYP+BDq8VAEgAxmNGYcPU8YpOc3DryEXj4zMzYQFrQuUm0YfzKaR2xbfjsImjXJN7C/TE1CYXsv3DeqIzgDRA/kII4LzqoICWm9mnwejER1kMu1Vf+1NWbwUuYJjsQVQXYkwkWgnv53obevBZtjpgZqIzlStufIU+sPNEWSd9BlrLmiSEu6nXC5lbstyPJVaqihsFoBPNJ0Q+IgJUjqaxhTf6hGtNB3Rqcpv0ZT349NdK9mQ+9lAQYCwXdmYbELdlbZVSja0aJQlkf0TaAjixDbNcR32/VMIw98F2YxVRVWPnADUaJ9Bn8oa7NkOJIUfB7VAg1KtUl8IIwSXvRk436UtPZGxg+PQM7UXX/TgiBuqCQWdUChoH/QAoY2fyKRKgXJHnGdt+pBRQ2OYs7TZWCJLZsLKgnHV+eWh3Y3EB1hN9cmcszdnmYiyD1gCY8pSETFbWV01nVPvIuUTc+jMipv3NN81VQDS5/eU1VJNpRuDiufdBKJv0jjHQk+hTdqe+2GSmMD24ZG8FQXJZZPBCodWR1A81T8toCaIAGHnOfZeO7nxZu9Uo+6ohrVxc5F4szSizra+M3zfuFnm5FGgxCKt5uibLYgRyNcmR8/9vqTfMZgalTklbKHEFw1i+xOwrFrqRMh7FoovDRoI3QuaHLpV+ZUpZo3zTOQofdXPthKAmSLc11cjn509oTnnXUBBoBn/hErrwC/v8dZep1YEKM3wjfuIFsHRrsECswqNjwN/yOZCirm2VvFJEPMuKIwy+8jdNGncm8v4R9Br3c+wYJ8696L7Dg0iFShoyoP4OqIvBNY+dYyy935yGkIF2KI6l01xQZcWoHSVKPd6/78Iwy4lTKhtOqtu7ETJqOE53gQpR9jaAY0RiBB1SLm+Jbwt3ipSJiCDgKmkVmk5AU9HC0XYR/erjg13HF4hIcpLPW1ZWMKSxTqZ8z8FMJilInBgfcBwvjNE5seWvdFKltvlItnGhSh7BLUZ5UInDhl00NJBE2PdstDvRvQjLKvYUoFly3jONVsUfuQpzrcjT0g6gEgL8ZtlmaF11owcCvqhNDxWuTAJTX/xXf6WehxEB0qy3xCdxahbuneS3DPI0z2kAQwrx19i5r+RKQ8bWDaQ/OGY47sLPJgDgijEz16CvAMBSN0PvOso6FstsT/ynR3LLTPcY0QDw21Dv3wNHNa9HbanJcb3/MuhZGlrKp7"
"scandit": "ATSVF4WBEUdWFabwSBws+xhCeCSCzgKZVEUjDXt0v6EpJHyN7lNmjMNmg8S+ADBh6h/Wn6Vl1b8TDhw3Fl1ZdkFoQ88zZUgagRY9vKpAjzimETtcVmzAA05W498GYgSr42+q4P9dkGO1RPdcOXqAgZZpNlsaQnyP1WjOMvgRRouwBxnoVCwkir8//kLxJaHPJKSYQNcTdRNMgqNPq/vUwdYVrzg26ltn7eC5imeXyYuQH3u2L4TVuRjr3SDVqsv7lnybh3ijg3dLoI93atUBuxbmzvoWzyb2mxrchJ9DaxrBy0igV2qFzzF1R6QvlNTyvN9HyUvZ0/sPS1DqOoql9bqG7ibyGOdRa2/vfIDTLbVEIaym8yQzErBBqthjviCub2pYXGX+ai9xXufuqRDyX29uCafxSv6sQsnVcEnuLEmP6gdmGBMVvH/WEZHnGn6bQpfWwFIGRZZKM+SxTdToJanj3jxNF/pO445/YZWJBDRT5nP55gESsrwiTXbb+i9lY4Hx7srEQJR07lJWASfKGX6IJtUaIstl7KnO6VI72XI2Zo01SAQAOw7m5+70LgYN1woYoAcziCSFyuIfJavGF0zd1cAu95Cwo0E8+y/YcAO3jwEqFE8oH7PkqKEf4XbF166quTf3AmVQJ8Q6lfSqWlZTps/dDGCAOe3Z63drIbh2bu3A/49bjT1TS7RFK5QvkKCtrM8zOS1DhEDjPPNR84BD/vbpjehHUlG6i7xlTwhmYblQR1oMUpfqrHqX5b9Lg2qADH+AfKRJ7Xd/kPSXdEw7MvJaZFpv9VuiFlUv37EyQBopyFhWYxRU9Kb1XfmkxpO+TCovzmEbKpWxi8KBYOdbX3QaNBW6HQLEd79+H8E="
},
"gender": {
"0": "Keine Anrede",

View File

@@ -73,7 +73,7 @@
},
"checkForUpdates": 3600000,
"licence": {
"scandit": "AZ70hgtZLmFWHbYP+BDq8VAEgAxmNGYcPU8YpOc3DryEXj4zMzYQFrQuUm0YfzKaR2xbfjsImjXJN7C/TE1CYXsv3DeqIzgDRA/kII4LzqoICWm9mnwejER1kMu1Vf+1NWbwUuYJjsQVQXYkwkWgnv53obevBZtjpgZqIzlStufIU+sPNEWSd9BlrLmiSEu6nXC5lbstyPJVaqihsFoBPNJ0Q+IgJUjqaxhTf6hGtNB3Rqcpv0ZT349NdK9mQ+9lAQYCwXdmYbELdlbZVSja0aJQlkf0TaAjixDbNcR32/VMIw98F2YxVRVWPnADUaJ9Bn8oa7NkOJIUfB7VAg1KtUl8IIwSXvRk436UtPZGxg+PQM7UXX/TgiBuqCQWdUChoH/QAoY2fyKRKgXJHnGdt+pBRQ2OYs7TZWCJLZsLKgnHV+eWh3Y3EB1hN9cmcszdnmYiyD1gCY8pSETFbWV01nVPvIuUTc+jMipv3NN81VQDS5/eU1VJNpRuDiufdBKJv0jjHQk+hTdqe+2GSmMD24ZG8FQXJZZPBCodWR1A81T8toCaIAGHnOfZeO7nxZu9Uo+6ohrVxc5F4szSizra+M3zfuFnm5FGgxCKt5uibLYgRyNcmR8/9vqTfMZgalTklbKHEFw1i+xOwrFrqRMh7FoovDRoI3QuaHLpV+ZUpZo3zTOQofdXPthKAmSLc11cjn509oTnnXUBBoBn/hErrwC/v8dZep1YEKM3wjfuIFsHRrsECswqNjwN/yOZCirm2VvFJEPMuKIwy+8jdNGncm8v4R9Br3c+wYJ8696L7Dg0iFShoyoP4OqIvBNY+dYyy935yGkIF2KI6l01xQZcWoHSVKPd6/78Iwy4lTKhtOqtu7ETJqOE53gQpR9jaAY0RiBB1SLm+Jbwt3ipSJiCDgKmkVmk5AU9HC0XYR/erjg13HF4hIcpLPW1ZWMKSxTqZ8z8FMJilInBgfcBwvjNE5seWvdFKltvlItnGhSh7BLUZ5UInDhl00NJBE2PdstDvRvQjLKvYUoFly3jONVsUfuQpzrcjT0g6gEgL8ZtlmaF11owcCvqhNDxWuTAJTX/xXf6WehxEB0qy3xCdxahbuneS3DPI0z2kAQwrx19i5r+RKQ8bWDaQ/OGY47sLPJgDgijEz16CvAMBSN0PvOso6FstsT/ynR3LLTPcY0QDw21Dv3wNHNa9HbanJcb3/MuhZGlrKp7"
"scandit": "AbBVKBt1M6NjGVMLDyT7EBwD7Baj5eMzG0k8HT1QSQbUGAFCXXqF73RfxM88FluMPljT8WdVsHkvZcnrZmRhLRVGTU4rclBlVWYck0VozFbIbERw0GyFytcpKt78WTqihXGIkZFEoxcPH5YU63s1x/NDYJMYVvoT3CX+jYl/wGmLOSs/uH8u8p9wpNbjBx3IF0Yu6CA+gGDFP8RngRoRZtBvaLU4IEdk30Ehmg8iCso2Wl+8ePGYgRL+JndZ9B7ZI0lw2YBdsoCoPAVEUB0Ta1osx3rZ9eAmCSLlpCbJtDspHPqVFiQ6a2eBV9Wl5YZ2qrW8NYZ5GntJfytySqka9kOu3nubq04UMuZ6KyNkXjlUO1OvlFYBYW7eudeGParR1iJLPZMghJBOiWPv3nHMxWyxOXhZQKr1zhYgolbceOClnmIPF4JdDgpCwe4RdPTggYTU2Jh1YgPj67tNbijj8OtH7xMpALEOBAJ1/z6zNkYtLAS0qcwzH+QWwSC+I7vP1ne//ODsHLToUbe2LJoUEEht74NPTLWaLMTmmtfPrcoXSQX23yfrc/96d389JppSHp6vGK/CixEeSdrmLmdLYtTbH4mNqP53kp80fGPEd8FXZkFEpjtXtLQiQoP5ug5014FYFqpWqPzICAPhup4HWwSEKiNQ6UfWx9lbFSJYkbrP1JpLf9USNA0LyXN0b1IFNPr57Q25xPerJ04WUjWbfZ1+WZsS58CBjjggcdx4LDKv5/NaHq/wEDcxrt42tQlaCzZezneSZYJSS3cyB8o8C83XwWXo/l8fpbdvyB4O7DJEcL6vWS8jSyiIP8eKSRS81Dkv1UjZfjfomaF8Fh7bZYeatf4gSR3MH7aeaHy0LyVt6RX7Ly99WaVv0qWf3T6w"
},
"gender": {
"0": "Keine Anrede",

View File

@@ -74,8 +74,7 @@
},
"checkForUpdates": 3600000,
"licence": {
"scandit": "Ac2kvx5ZOzjvFl/LuAd6wds3C30YJ4g8Cm6PX4sgUnKPePVMuH+rFQIyVNn1YdS3myORojEOBsIZWhMw2nRUGBtOnQ5FO+cRHgQu0pkP+VG6OYvt8ETUTn8Aa2f9bmfqclO3LI8WN8psWr+adkZEtqNTvCgyDLZaICh8S7RfmwJVVWaOPX4LDagGhLDPS2YQdg+ibpR0l0ZlX2h/3GttofE64HOlBN3QtDB8yihHJNgVcUVy2UQVS+BXOyvIfZEFbFgPYVt5HZ0aQgcISlYVAmJvRsHyeKYRUnIi3ZN73EQmHzWcOV4/HWVoTs1MTW0mxV074vNwqExYW9LYmz9zgLUD7FMnKMFClkzRBHRN1CC7brosCnFkZWQp3CV4Ua48Fn9GW0Zpn/4MIZgzSU26inl5ZnT3dCc2+3BH3Us1uugTUrOPwFuwsPpr4NZYXWJMOmcm4kBBVJd0Uwk28GyZM7x1hXADcQgcc23+gDtbbUZWVmr3TE7GBcV3j+XUeOk8nHZw3DsYJ46MT2sSfks3QXRl4tBkBad6M+UxW4tb2IQC/4K9IXKhDN8VYXpzrrRHJNvOiH5+NrixthDZHHd/MGNuBDrJFOuXq8L7O6PxBoVZ0NPXmCO5vKyYdhBz5gJ5u3vNkSke7p+cDcvFicsVyNWRaaoFL0UN9gxFVMY8hkJKBZyGxZL2LEDXD44PxPsDnygpDC1Jyc7pkhEA0fKSc9aXZb1HDpwe1hqyyRVBtHkgPiN78GmJImbaUlj8XsK3yVyAjs2XvPR0/3ASHS53ViwzWKL3Oi8I515IJDtDhlvrkeh7MrWMaEu9k6ZQXJi1uJsh3JGfyS+yDlPjePVdsVqnZ4uw9pKMXvjlJeNcIiGM2Cf5S89nk2Qe/56MrKB9Frm6Q5wQHai8TNdCZYBi67dmAX8KHPXvEU4K6KyyW89YGcabZQ3eOJDr4oqW9ZcYPBttREdH3WI/HxvpEq6bqoDhT9AxpIWEMVb6y/DcDHSEresepibug4qOr9xOPq0yk2uiWYhPubFnCk7thQCXOGv9crWnQoOrt9c1qoaWXM4YmKqfcaQ67Tn+uFQmYTZyqw4jlJU4GgKe5/GNCVQM5aNUg1J0Px1NlFCS+rrIDyMQp0byFcgTd/E9sA5d1+YZKHKmJiQwEAz6oU9yyoUlxntSI42GHB/UttPc7Hj14V5+oJ+Yz+CZodmkXFg57Vx4NuxveNtO"
},
"scandit": "ApI1Sg5/KzWICPhn0CbflI4cjgXiFkKnhgEmUvAt0D3CWsck0SCIm557hJvGTqXD0A1mt3IvEwA8eQ1CBXL3EoA9lASWUcLt+FSWP9gHao+LT6Oz9QMrsJoJRC/OboodKS4/F+ZVa02eUT53X0GX9jJeEnh8EerqZimrl6oDjNLvHCzBnxtmsMZidAUaErqK5yaQQCkUKcfTQhRzVhqvsjdENR76EmrrvCSr93oMCnnDHjcyOz8O3stcNrCOGbxwDBIMwf05CzoEBhxF9SoT/fwvfWa9BRvlMTxl9lUUE2f3Aw9+0CBG7PYgZ9XGCiCM2Wy9T5cf0C5MOLr2MAIgQrlDua0oEtmC5FjFojQHJEITRmLyQnAyUU8Y+jkUUCtQNmweZKtTQT9le+G9QCzRoSsmVsVxCKxII3+8iLA+Lh9meI/vJSaQ2VpDgZVrV1Vc4V/z0Exu7Ap7R0MpzCy4hhRzdpWgf4OG815ZctwMvM7qfBqykG98B9oP3YC/LG+cpVK4Ipx5VnWBUIwVHDiocHhMjyroTBAeH3BfeCdOEpKwNK9vOxrbvUpqAc8ZOaaal08hWgFVFR8BQN+rEkiqKx5fONRXefkkyUWMdqwvoBn7ZzCr+F9GmD52Q7ZuDcyAigm2ArwDipT9QUH7gxphogcKRNAWAyaENWWKRBFWmeNYXJOuGXLr05Zye7joGFbJHxPYyUJ6KMombmYlI2GHc4JQGJNneDuL93v8AkYcfM2WfOjf0hm+SVw0TP95bD1xJwSCoKO5L6FxqMu5GPcOqik3sjGHg6XsEr10m7jt7G2PfNTgS3ft+TP32OjeSu9M80Fu3nmeqLM4a4lx9fFbGMpWDEU9wdftmPByeW7KoXyS2bkd1Mg9UP8ci0nKo2d/ThPn+iMEjXSibNeIGibaIT4ys3pjDLW2mx0IxQpwnuQfZzAHBszpMkwKuG4+FrqXff9+bZGuRQlVwhm2v5xbKRjgi99i14QkuNVUkePxllLZGFgQH0DjsLINZb+R9stBYjQmMGc2kkJfyhHx2/zvT2D2mpgcaq0ZRKco2CqDiLUJoHwLPse/fu4PWvqSKVpwiqhCehuloWTE3jkFUncwDI50hPvrfCx92cOJUE8RTsQgDoAh7JKsPHctSZfUicZyLHOuHMhtIoxs6l/lzFowbhZob/Uo7aRsipOcP/iZgEPnMEu/obXcLR3QrlQ+WuEppU4g2MZ9+xENLCqVDLEHiz+jZIvl42ePc4Ip4lJ5RQFcSSR1yYb+z/4KB/3bc308PHnEMEB5TYvVpK7M3kg2CTjos5lh733qQKwqYamgFjpr5oPUxRYwRvj41GYpcLN3Tr4WOi4lfevR5eVFBu1Jc9baY8JIOvcCL5WhXsEemnx5dUhcnP2ozloFCvU1IS60KHkXtF4NJl89tu5EECquTN5Lf9cvtIhlbmPsVg==" },
"gender": {
"0": "Keine Anrede",
"1": "Enby",

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,22 +1,20 @@
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';
import { UiModalService } from '@ui/modal';
import { PrintModalComponent, PrintModalData } from '@modal/printer';
import { groupBy } from '@ui/common';
import { NativeContainerService } from '@external/native-container';
import { ReceiptDTO } from '@swagger/oms';
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 _environmentSerivce = inject(EnvironmentService);
constructor() {
super('PRINT_SHIPPINGNOTE');
}
@@ -51,7 +49,7 @@ export class PrintShippingNoteActionHandler extends ActionHandler<OrderItemsCont
content: PrintModalComponent,
config: { showScrollbarY: false },
data: {
printImmediately: !this.nativeContainerService.isNative,
printImmediately: !this._environmentSerivce.matchTablet(),
printerType: 'Label',
print: async (printer) => await this.printShippingNoteHelper(printer, receipts),
} as PrintModalData,

View File

@@ -1,56 +1,77 @@
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';
import { UiModalService } from '@ui/modal';
import { PrintModalComponent, PrintModalData } from '@modal/printer';
import { NativeContainerService } from '@external/native-container';
import { groupBy } from '@ui/common';
import { Group, groupBy } from '@ui/common';
import { DomainPrinterService, Printer } from '@domain/printer';
import { firstValueFrom } from 'rxjs';
import { EnvironmentService } from '@core/environment';
import { ReceiptDTO, ResponseArgs } from '@swagger/oms';
@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 _environmentSerivce = inject(EnvironmentService);
private _domainPrinterService = inject(DomainPrinterService);
constructor() {
super('PRINT_SMALLAMOUNTINVOICE');
}
async handler(data: OrderItemsContext): Promise<OrderItemsContext> {
await this.uiModal
.open({
content: PrintModalComponent,
config: { showScrollbarY: false },
data: {
printImmediately: !this.nativeContainerService.isNative,
printerType: 'Label',
print: async (printer) => {
try {
const receipts = data?.receipts?.filter((r) => r?.receiptType & 128);
for (const group of groupBy(receipts, (receipt) => receipt?.buyer?.buyerNumber)) {
await this.omsPrintService
.OMSPrintKleinbetragsrechnung({
data: group?.items?.map((r) => r?.id),
printer,
})
.toPromise();
}
return {
error: false,
};
} catch (error) {
console.error(error);
return {
error: true,
message: error?.message || error,
};
}
},
} as PrintModalData,
})
.afterClosed$.toPromise();
private _printKleinbetragsrechnungHelper(printer: string, receiptGroup: Group<string, ReceiptDTO>): Promise<ResponseArgs> {
return firstValueFrom(
this.omsPrintService.OMSPrintKleinbetragsrechnung({
data: receiptGroup?.items?.map((r) => r?.id),
printer,
}),
);
}
async handler(data: OrderItemsContext): Promise<OrderItemsContext> {
const printerList = await firstValueFrom(this._domainPrinterService.getAvailableLabelPrinters());
let printer: Printer;
if (Array.isArray(printerList)) {
printer = printerList.find((printer) => printer.selected === true);
}
if (!printer || this._environmentSerivce.matchTablet()) {
await firstValueFrom(
this.uiModal.open({
content: PrintModalComponent,
config: { showScrollbarY: false },
data: {
printImmediately: !this._environmentSerivce.matchTablet(),
printerType: 'Label',
print: async (printer) => {
try {
const receipts = data?.receipts?.filter((r) => r?.receiptType & 128);
for (const group of groupBy(receipts, (receipt) => receipt?.buyer?.buyerNumber)) {
await this._printKleinbetragsrechnungHelper(printer, group);
}
return {
error: false,
};
} catch (error) {
console.error(error);
return {
error: true,
message: error?.message || error,
};
}
},
} as PrintModalData,
}).afterClosed$,
);
} else {
const receipts = data?.receipts?.filter((r) => r?.receiptType & 128);
for (const group of groupBy(receipts, (receipt) => receipt?.buyer?.buyerNumber)) {
await this._printKleinbetragsrechnungHelper(printer.key, group);
}
}
return data;
}
}

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

@@ -58,7 +58,7 @@ export class DomainGoodsService {
return this.abholfachService.AbholfachWareneingang({
filter: { orderitemprocessingstatus: '16;128;8192;1048576' },
input: {
customer_name: customerNumber,
customer_no: customerNumber,
},
});
}

View File

@@ -236,7 +236,9 @@ export class DomainOmsService {
}
if (!!organisation && !!buyer.organisation) {
buyer.organisation.name = organisation;
buyer.organisation = {
name: organisation,
};
}
return this.orderService

View File

@@ -53,7 +53,7 @@ export class PickupShelfInService extends PickupShelfIOService {
return this._abholfachService.AbholfachWareneingang({
filter: { orderitemprocessingstatus: '16;128;8192;1048576' },
input: {
customer_name: args.customerNumber,
customer_no: args.customerNumber,
},
});
}

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

@@ -4,6 +4,10 @@ import { map } from 'rxjs/operators';
import { WindowRef } from './window-ref.service';
import { ScanRequestType } from './scan-request.type';
import { Platform } from '@angular/cdk/platform';
/**
* @deprecated This service is deprecated and will be removed in future versions.
*/
@Injectable({
providedIn: 'root',
})

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

@@ -73,7 +73,7 @@
<ui-icon [rotate]="dropdown.opened ? '270deg' : '90deg'" icon="arrow_head"></ui-icon>
</button>
<ui-dropdown #statusDropdown yPosition="above" xPosition="after" [xOffset]="8">
<button uiDropdownItem *ngFor="let reason of reorderReasons$ | async" (click)="selectedReason = reason.value">
<button uiDropdownItem *ngFor="let reason of reorderReasons$ | async" (click)="selectedReason = reason.value; dropdown.close()">
{{ reason.value }}
</button>
</ui-dropdown>

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

@@ -164,6 +164,7 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
this.store.deliveryAvailability$,
this.store.deliveryDigAvailability$,
this.store.deliveryB2BAvailability$,
this.store.downloadAvailability$,
]).pipe(
map((availabilities) => {
return availabilities?.some((availability) => (availability as any)?.priceMaintained) ?? false;
@@ -177,8 +178,9 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
this.store.deliveryAvailability$,
this.store.deliveryDigAvailability$,
this.store.deliveryB2BAvailability$,
this.store.downloadAvailability$,
]).pipe(
map(([item, takeAway, pickUp, delivery, deliveryDig, deliveryB2B]) => {
map(([item, takeAway, pickUp, delivery, deliveryDig, deliveryB2B, download]) => {
const hasPickupOrTakeaway = takeAway?.inStock || pickUp?.inStock;
if (hasPickupOrTakeaway && item?.catalogAvailability?.price?.value?.value) {
@@ -201,6 +203,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
return deliveryB2B.price;
}
if (download?.price?.value?.value) {
return download.price;
}
return null;
}),
);

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

@@ -166,6 +166,7 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
if (!isEqual(cleanQueryParams, this.cleanupQueryParams(this.searchService.filter.getQueryParams()))) {
await this.searchService.setDefaultFilter(queryParams);
const data = await this.getCachedData(processId, queryParams, selectedBranch?.id);
if (data.items?.length > 0) {
this.searchService.setItems(data.items);
this.searchService.setHits(data.hits);
@@ -392,15 +393,14 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
});
}
getCachedData(processId: number, params: Record<string, string> = {}, branchId: number) {
async getCachedData(processId: number, params: Record<string, string> = {}, branchId: number) {
const qparams = this.cleanupQueryParams({ ...params, processId: String(processId), branchId: String(branchId) });
const cacheData = await this.cache.get<{
items: ItemDTO[];
hits: number;
}>(qparams);
return (
this.cache.get<{
items: ItemDTO[];
hits: number;
}>(qparams) || { items: [], hits: 0 }
);
return cacheData ?? { items: [], hits: 0 };
}
cleanupQueryParams(params: Record<string, string> = {}) {

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,7 @@
<div class="flex flex-row items-center h-14 bg-white relative rounded-t font-bold shadow-lg">
<h3 class="text-center grow font-bold text-h3">Packstück-Prüfung</h3>
<button
id="package-result-filter-button"
class="absolute right-0 top-0 h-14 rounded px-5 text-lg bg-cadet-blue grid grid-flow-col gap-2 items-center"
type="button"
(click)="openFilter()"
@@ -21,7 +22,7 @@
<shell-filter-overlay #filterOverlay class="relative">
<div class="relative">
<button type="button" class="absolute top-4 right-4 text-cadet" (click)="closeFilterOverlay()">
<button id="package-result-filter-button-close" type="button" class="absolute top-4 right-4 text-cadet" (click)="closeFilterOverlay()">
<shared-icon [icon]="'close'" [size]="28"></shared-icon>
</button>
</div>
@@ -40,6 +41,7 @@
<div class="absolute bottom-8 left-0 right-0 grid grid-flow-col gap-4 justify-center">
<button
id="package-result-filter-button-reset"
type="button"
class="px-6 py-4 font-bold bg-white text-brand border-2 border-solid border-brand rounded-full"
(click)="resetFilter()"
@@ -47,6 +49,7 @@
Filter zurücksetzen
</button>
<button
id="package-result-filter-button-apply"
type="button"
class="px-6 py-4 font-bold bg-brand text-white border-2 border-solid border-brand rounded-full disabled:bg-cadet-blue disabled:cursor-progress disabled:border-cadet-blue"
(click)="applyFilter()"

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';

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