mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Compare commits
33 Commits
feature/47
...
fix/4885-A
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2da3859536 | ||
|
|
1becbec412 | ||
|
|
cdc2553d73 | ||
|
|
05eb3cc756 | ||
|
|
6e1c434edf | ||
|
|
ed8e937924 | ||
|
|
1bd17fd887 | ||
|
|
c35c82eaab | ||
|
|
258faec021 | ||
|
|
4bcc523480 | ||
|
|
8900a77d7a | ||
|
|
895e2bd2ec | ||
|
|
4b10dd96d9 | ||
|
|
1126e4f0c1 | ||
|
|
e9f24a88d6 | ||
|
|
f30de35d51 | ||
|
|
0c6f8abbad | ||
|
|
54b37436eb | ||
|
|
02bae79e4a | ||
|
|
f2c95b6a16 | ||
|
|
d48680c59e | ||
|
|
775390b5df | ||
|
|
1788f566e3 | ||
|
|
d4e1088190 | ||
|
|
a8ecd1f07b | ||
|
|
2c239ac597 | ||
|
|
200eb7f217 | ||
|
|
694fc6d084 | ||
|
|
8ae990bcde | ||
|
|
1d472ce3df | ||
|
|
1d19779dac | ||
|
|
90e671d285 | ||
|
|
33fb44f20a |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -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
|
||||
@@ -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" ]
|
||||
|
||||
|
||||
35
angular.json
35
angular.json
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<div class="scanner-container" #scanContainer></div>
|
||||
<button class="close-scanner" type="button" (click)="close()">Scan abbrechen</button>
|
||||
17
apps/isa-app/.storybook/main.ts
Normal file
17
apps/isa-app/.storybook/main.ts
Normal 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;
|
||||
17
apps/isa-app/.storybook/preview.ts
Normal file
17
apps/isa-app/.storybook/preview.ts
Normal 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;
|
||||
10
apps/isa-app/.storybook/tsconfig.doc.json
Normal file
10
apps/isa-app/.storybook/tsconfig.doc.json
Normal 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"]
|
||||
}
|
||||
11
apps/isa-app/.storybook/tsconfig.json
Normal file
11
apps/isa-app/.storybook/tsconfig.json
Normal 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
4
apps/isa-app/.storybook/typings.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
declare module '*.md' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
373381
apps/isa-app/documentation.json
Normal file
373381
apps/isa-app/documentation.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1,23 +1,22 @@
|
||||
import { Injectable, isDevMode } from '@angular/core';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
import { Config } from '@core/config';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
|
||||
@Injectable()
|
||||
export class DevScanAdapter implements ScanAdapter {
|
||||
readonly name = 'Dev';
|
||||
|
||||
constructor(
|
||||
private _modal: UiModalService,
|
||||
private _environmentService: EnvironmentService,
|
||||
) {}
|
||||
private _modal = inject(UiModalService);
|
||||
|
||||
private _config = inject(Config);
|
||||
|
||||
async init(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
// return new Promise((resolve, reject) => {
|
||||
// resolve(isDevMode());
|
||||
// });
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(coerceBooleanProperty(this._config.get('dev-scanner')));
|
||||
});
|
||||
}
|
||||
|
||||
scan(): Observable<string> {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -37,7 +37,7 @@ export class ScanAdapterService {
|
||||
|
||||
for (const name of adapterOrder) {
|
||||
adapter = this.getAdapter(name);
|
||||
|
||||
console.log('adapter', adapter);
|
||||
if (adapter) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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, inject } from '@angular/core';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
|
||||
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-scandit-overlay',
|
||||
@@ -9,7 +10,10 @@ import { Barcode, BarcodePicker, ScanResult, ScanSettings } from 'scandit-sdk';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy {
|
||||
private _barcodePicker: BarcodePicker;
|
||||
private dataCaptureContext: DataCaptureContext;
|
||||
private dataCaptureView: DataCaptureView;
|
||||
private barcodeCapture: BarcodeCapture;
|
||||
private camera: Camera;
|
||||
|
||||
private _onScan?: (code: string) => void;
|
||||
|
||||
@@ -17,57 +21,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 +83,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,8 +28,10 @@ export class ScanditScanAdapter implements ScanAdapter {
|
||||
|
||||
async init(): Promise<boolean> {
|
||||
if (this._environmentService.isTablet()) {
|
||||
await configure(this._config.get('licence.scandit'), {
|
||||
engineLocation: '/scandit/',
|
||||
await configure({
|
||||
licenseKey: this._config.get('licence.scandit'),
|
||||
libraryLocation: new URL('scandit', document.baseURI).toString(),
|
||||
moduleLoaders: [barcodeCaptureLoader()],
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Component, effect, HostListener, Inject, OnInit, Renderer2, signal, untracked } from '@angular/core';
|
||||
import { Component, effect, HostListener, inject, Inject, Injector, OnInit, Renderer2, signal, untracked } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { ApplicationService } from '@core/application';
|
||||
@@ -10,7 +10,7 @@ import { asapScheduler, interval, Subscription } from 'rxjs';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { IsaLogProvider } from './providers';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { AuthService, LoginStrategy } from '@core/auth';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { injectOnline$ } from './services/network-status.service';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
@@ -35,6 +35,8 @@ import { animate, style, transition, trigger } from '@angular/animations';
|
||||
],
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
$online = toSignal(injectOnline$());
|
||||
|
||||
$offlineBannerVisible = signal(false);
|
||||
@@ -180,15 +182,9 @@ export class AppComponent implements OnInit {
|
||||
if (this._document.hidden && this._authService.isAuthenticated()) {
|
||||
this._authService.refresh();
|
||||
} else if (!this._authService.isAuthenticated()) {
|
||||
return this._modal
|
||||
.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Sie sind nicht mehr angemeldet',
|
||||
data: { message: 'Sie werden neu angemeldet' },
|
||||
})
|
||||
.afterClosed$.subscribe(() => {
|
||||
this._authService.login();
|
||||
});
|
||||
const strategy = this.injector.get(LoginStrategy);
|
||||
|
||||
return strategy.login('Sie sind nicht mehr angemeldet');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
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';
|
||||
import { PlatformModule } from '@angular/cdk/platform';
|
||||
|
||||
import { Config, ConfigModule, JsonConfigLoader } from '@core/config';
|
||||
import { AuthModule, AuthService } from '@core/auth';
|
||||
import { AuthModule, AuthService, LoginStrategy } from '@core/auth';
|
||||
import { CoreCommandModule } from '@core/command';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
@@ -45,21 +45,14 @@ import { firstValueFrom } from 'rxjs';
|
||||
registerLocaleData(localeDe, localeDeExtra);
|
||||
registerLocaleData(localeDe, 'de', localeDeExtra);
|
||||
|
||||
export function _appInitializerFactory(
|
||||
config: Config,
|
||||
auth: AuthService,
|
||||
injector: Injector,
|
||||
scanAdapter: ScanAdapterService,
|
||||
nativeContainer: NativeContainerService,
|
||||
networkStatus: NetworkStatusService,
|
||||
) {
|
||||
export function _appInitializerFactory(config: Config, injector: Injector) {
|
||||
return async () => {
|
||||
const statusElement = document.querySelector('#init-status');
|
||||
const laoderElement = document.querySelector('#init-loader');
|
||||
|
||||
try {
|
||||
let online = false;
|
||||
|
||||
const networkStatus = injector.get(NetworkStatusService);
|
||||
while (!online) {
|
||||
online = await firstValueFrom(networkStatus.online$);
|
||||
|
||||
@@ -72,24 +65,34 @@ export function _appInitializerFactory(
|
||||
|
||||
statusElement.innerHTML = 'Konfigurationen werden geladen...';
|
||||
await config.init();
|
||||
statusElement.innerHTML = 'Authentifizierung wird geprüft...';
|
||||
await auth.init();
|
||||
|
||||
if (auth.isAuthenticated()) {
|
||||
statusElement.innerHTML = 'App wird initialisiert...';
|
||||
const state = injector.get(RootStateService);
|
||||
await state.init();
|
||||
}
|
||||
|
||||
statusElement.innerHTML = 'Native Container wird initialisiert...';
|
||||
await nativeContainer.init();
|
||||
|
||||
statusElement.innerHTML = 'Scanner wird initialisiert...';
|
||||
const scanAdapter = injector.get(ScanAdapterService);
|
||||
await scanAdapter.init();
|
||||
|
||||
statusElement.innerHTML = 'Authentifizierung wird geprüft...';
|
||||
|
||||
const auth = injector.get(AuthService);
|
||||
try {
|
||||
await auth.init();
|
||||
} catch (error) {
|
||||
statusElement.innerHTML = 'Authentifizierung wird durchgeführt...';
|
||||
const strategy = injector.get(LoginStrategy);
|
||||
await strategy.login();
|
||||
}
|
||||
|
||||
statusElement.innerHTML = 'App wird initialisiert...';
|
||||
const state = injector.get(RootStateService);
|
||||
await state.init();
|
||||
|
||||
statusElement.innerHTML = 'Native Container wird initialisiert...';
|
||||
const nativeContainer = injector.get(NativeContainerService);
|
||||
await nativeContainer.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 +126,10 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, MainComponent],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
HttpClientModule,
|
||||
ShellModule.forRoot(),
|
||||
AppRoutingModule,
|
||||
AppSwaggerModule,
|
||||
@@ -160,7 +163,7 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: _appInitializerFactory,
|
||||
multi: true,
|
||||
deps: [Config, AuthService, Injector, ScanAdapterService, NativeContainerService, NetworkStatusService],
|
||||
deps: [Config, Injector],
|
||||
},
|
||||
{
|
||||
provide: NOTIFICATIONS_HUB_OPTIONS,
|
||||
@@ -182,7 +185,7 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
|
||||
useClass: IsaErrorHandler,
|
||||
},
|
||||
{ provide: LOCALE_ID, useValue: 'de-DE' },
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -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.' },
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { inject, Injectable, Injector } from '@angular/core';
|
||||
import { HttpInterceptor, HttpEvent, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
|
||||
import { NEVER, Observable, throwError } from 'rxjs';
|
||||
import { from, NEVER, Observable, throwError } from 'rxjs';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { catchError, filter, mergeMap, takeUntil, tap } from 'rxjs/operators';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { AuthService, LoginStrategy } from '@core/auth';
|
||||
import { IsaLogProvider } from '../providers';
|
||||
import { LogLevel } from '@core/logger';
|
||||
import { injectOnline$ } from '../services/network-status.service';
|
||||
@@ -11,6 +11,7 @@ import { injectOnline$ } from '../services/network-status.service';
|
||||
@Injectable()
|
||||
export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
readonly offline$ = injectOnline$().pipe(filter((online) => !online));
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
constructor(
|
||||
private _modal: UiModalService,
|
||||
@@ -27,18 +28,9 @@ export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
|
||||
handleError(error: HttpErrorResponse): Observable<any> {
|
||||
if (error.status === 401) {
|
||||
return this._modal
|
||||
.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Sie sind nicht mehr angemeldet',
|
||||
data: { message: 'Sie werden neu angemeldet' },
|
||||
})
|
||||
.afterClosed$.pipe(
|
||||
tap(() => {
|
||||
this._auth.login();
|
||||
}),
|
||||
mergeMap(() => NEVER),
|
||||
);
|
||||
const strategy = this.injector.get(LoginStrategy);
|
||||
|
||||
return from(strategy.login('Sie sind nicht mehr angemeldet')).pipe(mergeMap(() => NEVER));
|
||||
}
|
||||
|
||||
if (!error.url.endsWith('/isa/logging')) {
|
||||
|
||||
1
apps/isa-app/src/app/services/index.ts
Normal file
1
apps/isa-app/src/app/services/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './network-status.service';
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"interval": 300000
|
||||
},
|
||||
"debug": true,
|
||||
"dev-scanner": true,
|
||||
"@cdn/product-image": {
|
||||
"url": "https://produktbilder.paragon-data.net"
|
||||
},
|
||||
@@ -74,7 +75,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",
|
||||
|
||||
@@ -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": "AqeFthV/MMKEPoQNIB3vSLYDthFhJ0F03QQtH+4f/ivCRKdYPjxnMU94RVMEaldhNTQj5sB8mJVNWq0vbHCzqul36KcLdG0kwFfBiXAoEkfOe2bRGTCX4bASLuwfHVv8+AG+Pwdhelf3XMcIvnrGkiR91EmRGeebiiVX448H6U+WdyXJtns/W/ZgdMZBGUHA4WsG9Ct5SyLGaeGYI1iK8LZtpKzLBcsvYwOkDeI4IjIuOZpMpy6CzmBAHQlAHWKmwjDizWwB2rU2BZ6i+3H99mpvSz9PCWm9PS+Jr30Me13bb+Oz5zHxeMdoJtZNIhsTgWyVErUlcuceNIibrDj84L4qfmHKPQtalW10+w9ODwRIS+nLCWOpo9we+UCsFgMJLX3lH0ZIXEWEZjAxhzXmdxxGEcroQQXAIH3PsN8RUSuaC6PPOirvKmZUbW3XUun+vmxMWxhDyGwnat9CpDpQ+CpsyPECaUEkbkVEg/Mq42QxVHF25UgZ37c5gN0wHNAjal/HSpZfLBzDeC5Y/iKqgKhjf68Bf7lnOBYokWFUxBRdcKLhtz3nGNZL3UpabCULf2J5lOZ0Mj8hdC+P4UNZMCRVEs4UR9pqHEoJVdQ5KMO8cXcvKGxGG4hT9UNNbk9o+jNWOlhCribVTmkj6kmInB8zDFkceKy3HUSC8p9TlzjxfBpzN0oVMG9DIlkTWh3nryr4lDJimIz4AriI6Xft3NJgiIkUVAjsTHl33IRz7jwyQOzyUR197o0ojRwvLpm3zkHwap4lyvMz7SoYhKoyN66Aul3K5iic8hVVUuriChEZyIwYml71vAfIpmwZC5GVF5XJBT1r0OG+xmJbH6sae0gOnMpFyed3R+BH/AU2OY9nrnTNLN83pk8huK7BPQVnpAQqU76IrZP5GAyd1GNRi9WWJo4mHefe/9/x22lfHg7BELhOXoJlDZWoj4uOYJVVycQD/ninQMtwkry/9VEOQmrg76bRVbz2OZ3RFDw/AXBd+1jA0K7gIP9G5dN4x2NjNbzPE4gMhHvNi+vUy8x+1uHRQdBzI/F7EkuFb59eKZYe1EHTofnzGofZUgiuXMDDVTi8dE80PmFRCTnNvEtK8rRcBFSqWxeX1u5h+PR8btTagOH0hNCNWUaVYpIcHXvKP5gFFluPy5+RR3TRXYhBKOeb+Q2uxrowwVJs2FOxwfORtKXti8pGIw9bVZk9yNCqafPuURqGKMw/e+H8ElIWaiWH2mcY9dDKN6lBhOdKYjhKQZ/4t9H+ZbyeKzebH8habpAZEDdN0fbqDMwWTD+eKo02s5wOzJ+0z4BpDszMd2acvQ1GVrF0KajpReco2FE+AQpbxHM2KQfKqiDHOUd02nG9AHjKRf/xUTySpD8pG3DvPZC+ImqQZN/t7/IegQptgrezq2w2y0L89sgNnnhRopaMRt/sPSirTXh/NA=="
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
|
||||
@@ -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": "AqeFthV/MMKEPoQNIB3vSLYDthFhJ0F03QQtH+4f/ivCRKdYPjxnMU94RVMEaldhNTQj5sB8mJVNWq0vbHCzqul36KcLdG0kwFfBiXAoEkfOe2bRGTCX4bASLuwfHVv8+AG+Pwdhelf3XMcIvnrGkiR91EmRGeebiiVX448H6U+WdyXJtns/W/ZgdMZBGUHA4WsG9Ct5SyLGaeGYI1iK8LZtpKzLBcsvYwOkDeI4IjIuOZpMpy6CzmBAHQlAHWKmwjDizWwB2rU2BZ6i+3H99mpvSz9PCWm9PS+Jr30Me13bb+Oz5zHxeMdoJtZNIhsTgWyVErUlcuceNIibrDj84L4qfmHKPQtalW10+w9ODwRIS+nLCWOpo9we+UCsFgMJLX3lH0ZIXEWEZjAxhzXmdxxGEcroQQXAIH3PsN8RUSuaC6PPOirvKmZUbW3XUun+vmxMWxhDyGwnat9CpDpQ+CpsyPECaUEkbkVEg/Mq42QxVHF25UgZ37c5gN0wHNAjal/HSpZfLBzDeC5Y/iKqgKhjf68Bf7lnOBYokWFUxBRdcKLhtz3nGNZL3UpabCULf2J5lOZ0Mj8hdC+P4UNZMCRVEs4UR9pqHEoJVdQ5KMO8cXcvKGxGG4hT9UNNbk9o+jNWOlhCribVTmkj6kmInB8zDFkceKy3HUSC8p9TlzjxfBpzN0oVMG9DIlkTWh3nryr4lDJimIz4AriI6Xft3NJgiIkUVAjsTHl33IRz7jwyQOzyUR197o0ojRwvLpm3zkHwap4lyvMz7SoYhKoyN66Aul3K5iic8hVVUuriChEZyIwYml71vAfIpmwZC5GVF5XJBT1r0OG+xmJbH6sae0gOnMpFyed3R+BH/AU2OY9nrnTNLN83pk8huK7BPQVnpAQqU76IrZP5GAyd1GNRi9WWJo4mHefe/9/x22lfHg7BELhOXoJlDZWoj4uOYJVVycQD/ninQMtwkry/9VEOQmrg76bRVbz2OZ3RFDw/AXBd+1jA0K7gIP9G5dN4x2NjNbzPE4gMhHvNi+vUy8x+1uHRQdBzI/F7EkuFb59eKZYe1EHTofnzGofZUgiuXMDDVTi8dE80PmFRCTnNvEtK8rRcBFSqWxeX1u5h+PR8btTagOH0hNCNWUaVYpIcHXvKP5gFFluPy5+RR3TRXYhBKOeb+Q2uxrowwVJs2FOxwfORtKXti8pGIw9bVZk9yNCqafPuURqGKMw/e+H8ElIWaiWH2mcY9dDKN6lBhOdKYjhKQZ/4t9H+ZbyeKzebH8habpAZEDdN0fbqDMwWTD+eKo02s5wOzJ+0z4BpDszMd2acvQ1GVrF0KajpReco2FE+AQpbxHM2KQfKqiDHOUd02nG9AHjKRf/xUTySpD8pG3DvPZC+ImqQZN/t7/IegQptgrezq2w2y0L89sgNnnhRopaMRt/sPSirTXh/NA=="
|
||||
},
|
||||
"gender": {
|
||||
"0": "Keine Anrede",
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"silentRefresh": {
|
||||
"interval": 300000
|
||||
},
|
||||
"debug": true,
|
||||
"debug": false,
|
||||
|
||||
"@cdn/product-image": {
|
||||
"url": "https://produktbilder.paragon-data.net"
|
||||
},
|
||||
@@ -74,8 +75,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",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { coerceArray, coerceStringArray } from '@angular/cdk/coercion';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { coerceArray } from '@angular/cdk/coercion';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Config } from '@core/config';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
|
||||
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
|
||||
import { asapScheduler, BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -44,21 +44,26 @@ export class AuthService {
|
||||
this._oAuthService.tokenValidationHandler = new JwksValidationHandler();
|
||||
|
||||
this._oAuthService.setupAutomaticSilentRefresh();
|
||||
try {
|
||||
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
|
||||
} catch (error) {
|
||||
this.login();
|
||||
|
||||
throw error;
|
||||
}
|
||||
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
|
||||
|
||||
this._initialized.next(true);
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
return this.isIdTokenValid();
|
||||
}
|
||||
|
||||
isIdTokenValid() {
|
||||
console.log('ID Token Expiration:', new Date(this._oAuthService.getIdTokenExpiration()));
|
||||
return this._oAuthService.hasValidIdToken();
|
||||
}
|
||||
|
||||
isAccessTokenValid() {
|
||||
console.log('ACCESS Token Expiration:', new Date(this._oAuthService.getAccessTokenExpiration()));
|
||||
return this._oAuthService.hasValidAccessToken();
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this._oAuthService.getAccessToken();
|
||||
}
|
||||
@@ -99,9 +104,6 @@ export class AuthService {
|
||||
|
||||
async logout() {
|
||||
await this._oAuthService.revokeTokenAndLogout();
|
||||
// asapScheduler.schedule(() => {
|
||||
// window.location.reload();
|
||||
// }, 250);
|
||||
}
|
||||
|
||||
hasRole(role: string | string[]) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './auth.module';
|
||||
export * from './auth.service';
|
||||
export * from './if-role.directive';
|
||||
export * from './login.strategy';
|
||||
|
||||
78
apps/isa-app/src/core/auth/login.strategy.ts
Normal file
78
apps/isa-app/src/core/auth/login.strategy.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { ScanAdapterService } from '@adapter/scan';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { UiConfirmModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||
import { injectNetworkStatus$ } from '../../app/services';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthService as IsaAuthService } from '@swagger/isa';
|
||||
import { firstValueFrom, lastValueFrom } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LoginStrategy {
|
||||
private readonly environmentService = inject(EnvironmentService);
|
||||
private readonly networkStatus = toSignal(injectNetworkStatus$());
|
||||
private readonly modal = inject(UiModalService);
|
||||
private readonly scanAdapterService = inject(ScanAdapterService);
|
||||
private readonly isaAuthService = inject(IsaAuthService);
|
||||
private readonly authService = inject(AuthService);
|
||||
|
||||
async login(title = 'Anmeldung') {
|
||||
console.log('LoginStrategy.login');
|
||||
|
||||
let loginModalResult: UiModalResult<boolean>;
|
||||
|
||||
if (this.authService.isIdTokenValid()) {
|
||||
console.log('LoginStrategy.login: idToken is valid');
|
||||
await this.authService.login();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.environmentService.isMobileDevice()) {
|
||||
console.log('LoginStrategy.login: isMobileDevice');
|
||||
do {
|
||||
const loginModal = this.modal.open({
|
||||
content: UiConfirmModalComponent,
|
||||
title,
|
||||
config: {
|
||||
canClose: false,
|
||||
backdropClose: false,
|
||||
},
|
||||
data: {
|
||||
message: 'Bitte wählen Sie die Anmeldeoption aus.',
|
||||
rejectLabel: 'Anmeldung mit Logindaten',
|
||||
confirmLabel: 'Anmeldung mit Keycard',
|
||||
},
|
||||
});
|
||||
|
||||
loginModalResult = await loginModal.afterClosed$.toPromise();
|
||||
} while (this.networkStatus() === 'offline');
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
try {
|
||||
if (loginModalResult.data) {
|
||||
const result = await lastValueFrom(this.scanAdapterService.scan());
|
||||
|
||||
if (typeof result === 'string') {
|
||||
const res = await firstValueFrom(
|
||||
this.isaAuthService.AuthLogin({
|
||||
code: result,
|
||||
application: 'isa',
|
||||
hostname: location.host,
|
||||
}),
|
||||
);
|
||||
|
||||
if (res.token) {
|
||||
console.log('LoginStrategy.login: setKeyCardToken', res.token);
|
||||
this.authService.setKeyCardToken(res.token);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
console.log('LoginStrategy.login: login');
|
||||
await this.authService.login();
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
describe('Breadcrumb Actions', () => {});
|
||||
|
||||
@@ -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' });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
@@ -62,6 +62,10 @@ export class EnvironmentService {
|
||||
|
||||
matchDesktopXXLarge$ = this._breakpointObserver.observe(MATCH_DESKTOP_XXLARGE).pipe(map((result) => result.matches));
|
||||
|
||||
isMobileDevice(): boolean {
|
||||
return this._platform.ANDROID || this._platform.IOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `matchDesktopSmall` or 'matchDesktop' instead.
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
// });
|
||||
// });
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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[]) {
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,9 @@ export class DomainOmsService {
|
||||
}
|
||||
|
||||
if (!!organisation && !!buyer.organisation) {
|
||||
buyer.organisation.name = organisation;
|
||||
buyer.organisation = {
|
||||
name: organisation,
|
||||
};
|
||||
}
|
||||
|
||||
return this.orderService
|
||||
|
||||
@@ -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: [] })),
|
||||
|
||||
@@ -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',
|
||||
})
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>({
|
||||
|
||||
@@ -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: {},
|
||||
});
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
11
apps/isa-app/src/modal/message/message-modal.injector.ts
Normal file
11
apps/isa-app/src/modal/message/message-modal.injector.ts
Normal 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 });
|
||||
};
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './modal-printer.component';
|
||||
export * from './modal-printer.data';
|
||||
export * from './modal-printer.module';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {}
|
||||
@@ -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,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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$();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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({});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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({});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user