Upgrade isa-app project

This commit is contained in:
Lorenz Hilpert
2025-03-03 13:28:03 +01:00
parent 1b821db248
commit df47b932b6
92 changed files with 703 additions and 685 deletions

3
.gitignore vendored
View File

@@ -58,3 +58,6 @@ libs/swagger/src/lib/*
.nx/cache .nx/cache
.nx/workspace-data .nx/workspace-data
.angular .angular
storybook-static

View File

@@ -0,0 +1,55 @@
import nx from '@nx/eslint-plugin';
import baseConfig from '../../eslint.config.mjs';
export default [
...baseConfig,
...nx.configs['flat/angular'],
...nx.configs['flat/angular-template'],
{
files: ['**/*.ts'],
rules: {
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
'@angular-eslint/component-selector': [
'error',
{
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
},
},
{
files: ['**/*.ts'],
rules: {
'@typescript-eslint/no-unused-expressions': 'warn',
'prefer-const': 'warn',
'@angular-eslint/contextual-lifecycle': 'warn',
'@typescript-eslint/no-explicit-any': 'warn',
'@angular-eslint/no-empty-lifecycle-method': 'warn',
'@typescript-eslint/no-inferrable-types': 'warn',
'@angular-eslint/component-selector': 'warn',
'@angular-eslint/prefer-standalone': 'warn',
'@typescript-eslint/no-inferrable-types': 'warn',
'no-empty-function': 'warn',
'@typescript-eslint/no-empty-function': 'warn',
'@typescript-eslint/no-unused-vars': 'warn',
'@angular-eslint/directive-selector': 'warn',
},
},
{
files: ['**/*.html'],
// Override or add rules here
rules: {
'@angular-eslint/template/elements-content': 'warn',
'@angular-eslint/template/no-autofocus': 'warn',
},
},
];

View File

@@ -0,0 +1,21 @@
export default {
displayName: 'isa-app',
preset: '../../jest.preset.js',
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
coverageDirectory: '../../coverage/apps/prj',
transform: {
'^.+\\.(ts|mjs|js|html)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
},
],
},
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
'jest-preset-angular/build/serializers/html-comment',
],
};

View File

@@ -29,4 +29,4 @@
} }
} }
] ]
} }

View File

@@ -2,19 +2,12 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json", "$schema": "../../node_modules/nx/schemas/project-schema.json",
"name": "isa-app", "name": "isa-app",
"projectType": "application", "projectType": "application",
"generators": {
"@schematics/angular:component": {
"style": "scss"
},
"@schematics/angular:application": {
"strict": true
}
},
"sourceRoot": "apps/isa-app/src",
"prefix": "app", "prefix": "app",
"sourceRoot": "apps/isa-app/src",
"tags": [],
"targets": { "targets": {
"build": { "build": {
"executor": "@angular-devkit/build-angular:browser", "executor": "@angular-devkit/build-angular:application",
"options": { "options": {
"allowedCommonJsDependencies": [ "allowedCommonJsDependencies": [
"lodash", "lodash",
@@ -27,8 +20,8 @@
], ],
"outputPath": "dist/isa-app", "outputPath": "dist/isa-app",
"index": "apps/isa-app/src/index.html", "index": "apps/isa-app/src/index.html",
"main": "apps/isa-app/src/main.ts", "browser": "apps/isa-app/src/main.ts",
"polyfills": "apps/isa-app/src/polyfills.ts", "polyfills": ["zone.js"],
"tsConfig": "apps/isa-app/tsconfig.app.json", "tsConfig": "apps/isa-app/tsconfig.app.json",
"inlineStyleLanguage": "scss", "inlineStyleLanguage": "scss",
"assets": [ "assets": [
@@ -43,12 +36,8 @@
"output": "scandit" "output": "scandit"
} }
], ],
"styles": [ "styles": ["apps/isa-app/src/styles.scss"],
"apps/isa-app/src/styles.scss" "scripts": []
],
"scripts": [],
"serviceWorker": true,
"ngswConfigPath": "apps/isa-app/ngsw-config.json"
}, },
"configurations": { "configurations": {
"production": { "production": {
@@ -69,21 +58,17 @@
"with": "apps/isa-app/src/environments/environment.prod.ts" "with": "apps/isa-app/src/environments/environment.prod.ts"
} }
], ],
"outputHashing": "all" "outputHashing": "all",
"serviceWorker": "apps/isa-app/ngsw-config.json"
}, },
"development": { "development": {
"buildOptimizer": false,
"optimization": false, "optimization": false,
"vendorChunk": true,
"extractLicenses": false, "extractLicenses": false,
"sourceMap": true, "sourceMap": true
"namedChunks": true
} }
}, },
"defaultConfiguration": "production", "defaultConfiguration": "production",
"outputs": [ "outputs": ["{options.outputPath}"]
"{options.outputPath}"
]
}, },
"serve": { "serve": {
"executor": "@angular-devkit/build-angular:dev-server", "executor": "@angular-devkit/build-angular:dev-server",
@@ -103,56 +88,23 @@
"buildTarget": "isa-app:build" "buildTarget": "isa-app:build"
} }
}, },
"lint": {
"executor": "@nx/eslint:lint"
},
"test": { "test": {
"executor": "@angular-devkit/build-angular:karma", "executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": { "options": {
"tsConfig": "apps/isa-app/tsconfig.spec.json", "jestConfig": "apps/isa-app/jest.config.ts"
"karmaConfig": "karma.conf.js",
"polyfills": [
"zone.js",
"zone.js/testing"
],
"inlineStyleLanguage": "scss",
"assets": [
"apps/isa-app/src/favicon.ico",
"apps/isa-app/src/assets",
"apps/isa-app/src/manifest.webmanifest"
],
"styles": [
"apps/isa-app/src/styles.scss"
],
"scripts": []
} }
}, },
"storybook": { "serve-static": {
"executor": "@storybook/angular:start-storybook", "executor": "@nx/web:file-server",
"options": { "options": {
"configDir": "apps/isa-app/.storybook", "buildTarget": "isa-app:build",
"browserTarget": "isa-app:build", "staticFilePath": "dist/apps/isa-app/browser",
"compodoc": true, "spa": true
"compodocArgs": [
"-e",
"json",
"-d",
"apps/isa-app"
],
"port": 6006
}
},
"build-storybook": {
"executor": "@storybook/angular:build-storybook",
"options": {
"configDir": "apps/isa-app/.storybook",
"browserTarget": "isa-app:build",
"compodoc": true,
"compodocArgs": [
"-e",
"json",
"-d",
"apps/isa-app"
],
"outputDir": "storybook-static"
} }
} }
} }
} }

View File

@@ -5,7 +5,7 @@ import {
ViewChild, ViewChild,
NgZone, NgZone,
AfterViewInit, AfterViewInit,
OnDestroy, OnDestroy, OnInit,
} from '@angular/core'; } from '@angular/core';
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode'; import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core'; import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';
@@ -17,7 +17,7 @@ import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 's
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false, standalone: false,
}) })
export class ScanditOverlayComponent implements AfterViewInit, OnDestroy { export class ScanditOverlayComponent implements AfterViewInit, OnDestroy, OnInit {
private dataCaptureContext: DataCaptureContext; private dataCaptureContext: DataCaptureContext;
private dataCaptureView: DataCaptureView; private dataCaptureView: DataCaptureView;
private barcodeCapture: BarcodeCapture; private barcodeCapture: BarcodeCapture;

View File

@@ -27,7 +27,7 @@ export interface Breadcrumb {
/** /**
* Query Parameter * Query Parameter
*/ */
params?: Object; params?: object;
/** /**
* Timestamp * Timestamp

View File

@@ -1,7 +1,7 @@
import { createEntityAdapter, EntityState } from '@ngrx/entity'; import { createEntityAdapter, EntityState } from '@ngrx/entity';
import { Breadcrumb } from '../defs'; import { Breadcrumb } from '../defs';
export interface BreadcrumbState extends EntityState<Breadcrumb> {} export type BreadcrumbState = EntityState<Breadcrumb>
export const featureName = 'core-breadcrumb'; export const featureName = 'core-breadcrumb';

View File

@@ -34,7 +34,7 @@ export class CacheService {
return 'cache'; return 'cache';
} }
private getKey(token: Object | string): string { private getKey(token: object | string): string {
if (typeof token === 'string') { if (typeof token === 'string') {
return this.hash(token); return this.hash(token);
} }
@@ -105,7 +105,7 @@ export class CacheService {
}); });
} }
private async cached(token: Object | string): Promise<DbEntry<any> | undefined> { private async cached(token: object | string): Promise<DbEntry<any> | undefined> {
const store = await this.getObjectStore(); const store = await this.getObjectStore();
return new Promise<DbEntry<any> | undefined>((resolve, reject) => { return new Promise<DbEntry<any> | undefined>((resolve, reject) => {
const request = store.get(this.getKey(token)); const request = store.get(this.getKey(token));
@@ -118,7 +118,7 @@ export class CacheService {
}); });
} }
async get<T = any>(token: Object | string): Promise<T | undefined> { async get<T = any>(token: object | string): Promise<T | undefined> {
const cached = await this.cached(token); const cached = await this.cached(token);
if (!cached) { if (!cached) {
@@ -133,7 +133,7 @@ export class CacheService {
return cached.data; return cached.data;
} }
async delete(token: Object | string): Promise<void> { async delete(token: object | string): Promise<void> {
const store = await this.getObjectStore('readwrite'); const store = await this.getObjectStore('readwrite');
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const request = store.delete(this.getKey(token)); const request = store.delete(this.getKey(token));

View File

@@ -5,7 +5,7 @@
* @returns the value at the path or undefined * @returns the value at the path or undefined
* @throws if obj is not an object * @throws if obj is not an object
*/ */
export function pick<T = any>(path: string, obj: Object): T { export function pick<T = any>(path: string, obj: object): T {
const paths = path.split('.'); const paths = path.split('.');
// check if obj is null or undefined // check if obj is null or undefined

View File

@@ -165,7 +165,7 @@ export class DomainAvailabilityService {
quantity: number; quantity: number;
branch?: BranchDTO; branch?: BranchDTO;
}): Observable<AvailabilityDTO> { }): Observable<AvailabilityDTO> {
const request = !!branch ? this.getStockByBranch(branch.id) : this.getDefaultStock(); const request = branch ? this.getStockByBranch(branch.id) : this.getDefaultStock();
return request.pipe( return request.pipe(
switchMap((s) => switchMap((s) =>
combineLatest([ combineLatest([
@@ -222,7 +222,7 @@ export class DomainAvailabilityService {
quantity: number; quantity: number;
branchId?: number; branchId?: number;
}): Observable<AvailabilityDTO> { }): Observable<AvailabilityDTO> {
const request = !!branchId ? this.getStockByBranch(branchId) : this.getDefaultStock(); const request = branchId ? this.getStockByBranch(branchId) : this.getDefaultStock();
return request.pipe( return request.pipe(
switchMap((s) => this._stockService.StockInStockByEAN({ eans, stockId: s.id })), switchMap((s) => this._stockService.StockInStockByEAN({ eans, stockId: s.id })),
withLatestFrom(this.getTakeAwaySupplier(), this.getDefaultBranch()), withLatestFrom(this.getTakeAwaySupplier(), this.getDefaultBranch()),

View File

@@ -830,7 +830,7 @@ export class DomainCheckoutService {
const setSpecialComment$ = this.getSpecialComment({ processId }).pipe( const setSpecialComment$ = this.getSpecialComment({ processId }).pipe(
first(), first(),
mergeMap((specialComment) => { mergeMap((specialComment) => {
if (!!specialComment) { if (specialComment) {
return this.setSpecialCommentOnItem({ processId, specialComment }); return this.setSpecialCommentOnItem({ processId, specialComment });
} }
return of(specialComment); return of(specialComment);

View File

@@ -68,7 +68,7 @@ export class CrmCustomerService {
options: { take?: number; skip?: number; filter?: { [key: string]: string } } = { take: 20, skip: 0 }, options: { take?: number; skip?: number; filter?: { [key: string]: string } } = { take: 20, skip: 0 },
): Observable<ListResponseArgsOfCustomerInfoDTO> { ): Observable<ListResponseArgsOfCustomerInfoDTO> {
return this.customerService.CustomerListCustomers({ return this.customerService.CustomerListCustomers({
input: !!queryString ? { qs: queryString } : undefined, input: queryString ? { qs: queryString } : undefined,
take: options.take, take: options.take,
skip: options.skip, skip: options.skip,
filter: options.filter || {}, filter: options.filter || {},
@@ -85,7 +85,7 @@ export class CrmCustomerService {
} }
getCustomersByCustomerCardNumber(queryString: string): Observable<PagedResult<CustomerInfoDTO>> { getCustomersByCustomerCardNumber(queryString: string): Observable<PagedResult<CustomerInfoDTO>> {
return this.customerService.CustomerGetCustomerByBonuscard(!!queryString ? queryString : undefined); return this.customerService.CustomerGetCustomerByBonuscard(queryString ? queryString : undefined);
} }
getCustomer(customerId: number, eagerLoading?: number): Observable<Result<CustomerDTO>> { getCustomer(customerId: number, eagerLoading?: number): Observable<Result<CustomerDTO>> {

View File

@@ -68,7 +68,7 @@ export class PrintPriceDiffQrCodeLabelActionHandler extends ActionHandler<OrderI
}); });
const response = await this.domainPrinterService.printQrCode({ printer, data: payload }).toPromise(); const response = await this.domainPrinterService.printQrCode({ printer, data: payload }).toPromise();
if (!!response?.error) { if (response?.error) {
this.uiModal.open({ this.uiModal.open({
content: UiErrorModalComponent, content: UiErrorModalComponent,
title: 'Fehler beim Drucken des QR Code', title: 'Fehler beim Drucken des QR Code',

View File

@@ -244,7 +244,7 @@ export class DomainOmsService {
}) { }) {
const buyer: BuyerDTO = {}; const buyer: BuyerDTO = {};
if (!!communicationDetails) { if (communicationDetails) {
buyer.communicationDetails = { ...communicationDetails }; buyer.communicationDetails = { ...communicationDetails };
} }

View File

@@ -291,7 +291,7 @@ export class KulturpassOrderModalStore extends ComponentStore<KulturpassOrderMod
let isPriceMaintained = item?.catalogAvailability?.priceMaintained; let isPriceMaintained = item?.catalogAvailability?.priceMaintained;
let onlinePrice = -1; let onlinePrice = -1;
if (!!deliveryAvailability) { if (deliveryAvailability) {
isPriceMaintained = isPriceMaintained ?? deliveryAvailability['priceMaintained'] ?? false; isPriceMaintained = isPriceMaintained ?? deliveryAvailability['priceMaintained'] ?? false;
onlinePrice = deliveryAvailability?.price?.value?.value ?? -1; onlinePrice = deliveryAvailability?.price?.value?.value ?? -1;
} }

View File

@@ -71,8 +71,8 @@ export class PrintModalComponent implements OnInit, OnDestroy {
this.printers$.subscribe((printers) => { this.printers$.subscribe((printers) => {
const defaultPrinter = printers.find((p) => p.selected); const defaultPrinter = printers.find((p) => p.selected);
this.selectedPrinterKey = defaultPrinter?.key || printers[0]?.key; this.selectedPrinterKey = defaultPrinter?.key || printers[0]?.key;
if (!!defaultPrinter) { if (defaultPrinter) {
if (!!this.modalRef?.data?.printImmediately) { if (this.modalRef?.data?.printImmediately) {
this.print(); this.print();
} }
} }
@@ -83,7 +83,7 @@ export class PrintModalComponent implements OnInit, OnDestroy {
setError(errorMessage?: string) { setError(errorMessage?: string) {
this.error = true; this.error = true;
if (!!errorMessage) { if (errorMessage) {
this.errorMessage = errorMessage; this.errorMessage = errorMessage;
} }
} }

View File

@@ -105,7 +105,7 @@ export class PurchaseOptionsModalComponent implements OnInit, OnDestroy {
return; return;
} }
if (!!this._uiModalRef.data?.preSelectOption?.option) { if (this._uiModalRef.data?.preSelectOption?.option) {
this.store.setPurchaseOption(this._uiModalRef.data?.preSelectOption?.option); this.store.setPurchaseOption(this._uiModalRef.data?.preSelectOption?.option);
} }
}); });

View File

@@ -32,7 +32,7 @@ export class PriceUpdateItemComponent {
} }
get publicationDate() { get publicationDate() {
if (!!this.item?.product?.publicationDate) { if (this.item?.product?.publicationDate) {
const date = this._dateAdapter.parseDate(this.item.product.publicationDate); const date = this._dateAdapter.parseDate(this.item.product.publicationDate);
if (this._dateAdapter.getDate(date) === 1 && this._dateAdapter.getMonth(date) === 0) { if (this._dateAdapter.getDate(date) === 1 && this._dateAdapter.getMonth(date) === 0) {

View File

@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit, ViewChild, OnDestroy } from '@angular/core';
import { Config } from '@core/config'; import { Config } from '@core/config';
import { provideComponentStore } from '@ngrx/component-store'; import { provideComponentStore } from '@ngrx/component-store';
import { SharedFilterOverlayComponent } from '@shared/components/filter-overlay'; import { SharedFilterOverlayComponent } from '@shared/components/filter-overlay';
@@ -19,7 +19,7 @@ import { provideCancelSearchSubject } from '@shared/services/cancel-subject';
providers: [provideComponentStore(PriceUpdateComponentStore), provideCancelSearchSubject()], providers: [provideComponentStore(PriceUpdateComponentStore), provideCancelSearchSubject()],
standalone: false, standalone: false,
}) })
export class PriceUpdateComponent implements OnInit { export class PriceUpdateComponent implements OnInit, OnDestroy {
private _subscription = new Subscription(); private _subscription = new Subscription();
get breadcrumbKey(): string { get breadcrumbKey(): string {

View File

@@ -452,7 +452,7 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
items: [item], items: [item],
pickupBranch: selectedBranch, pickupBranch: selectedBranch,
inStoreBranch: selectedBranch, inStoreBranch: selectedBranch,
preSelectOption: !!selectedBranch ? { option: 'in-store', showOptionOnly: true } : undefined, preSelectOption: selectedBranch ? { option: 'in-store', showOptionOnly: true } : undefined,
}) })
.afterClosed$.subscribe(async (result) => { .afterClosed$.subscribe(async (result) => {
if (result?.data === 'continue') { if (result?.data === 'continue') {
@@ -505,7 +505,7 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
.toPromise(); .toPromise();
const crumb = crumbs[crumbs.length - 1]; const crumb = crumbs[crumbs.length - 1];
if (!!crumb) { if (crumb) {
await this._navigationService.getArticleSearchResultsPath(processId, { queryParams: crumb.params }).navigate(); await this._navigationService.getArticleSearchResultsPath(processId, { queryParams: crumb.params }).navigate();
} else { } else {
await this._navigationService.getArticleSearchBasePath(processId).navigate(); await this._navigationService.getArticleSearchBasePath(processId).navigate();

View File

@@ -47,7 +47,7 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
readonly fetchingItem$ = this.select((s) => s.fetchingItem); readonly fetchingItem$ = this.select((s) => s.fetchingItem);
readonly item$ = this.select((s) => s.item); readonly item$ = this.select((s) => s.item);
readonly itemData$ = this.select(this.item$, (item) => readonly itemData$ = this.select(this.item$, (item) =>
!!item item
? ({ ean: item?.product?.ean, itemId: item?.id, price: item?.catalogAvailability?.price } as ItemData) ? ({ ean: item?.product?.ean, itemId: item?.id, price: item?.catalogAvailability?.price } as ItemData)
: undefined, : undefined,
); );
@@ -99,7 +99,7 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
filter((item) => !!item?.id && !!item.catalogAvailability?.price?.value?.value), filter((item) => !!item?.id && !!item.catalogAvailability?.price?.value?.value),
tap(() => this.patchState({ fetchingPromotionPoints: true, fetchingPromotionPointsError: undefined })), tap(() => this.patchState({ fetchingPromotionPoints: true, fetchingPromotionPointsError: undefined })),
switchMap((item) => switchMap((item) =>
!!item item
? this.domainCatalogService ? this.domainCatalogService
.getPromotionPoints({ .getPromotionPoints({
items: [{ id: item.id, quantity: 1, price: item.catalogAvailability.price.value.value }], items: [{ id: item.id, quantity: 1, price: item.catalogAvailability.price.value.value }],

View File

@@ -114,7 +114,7 @@ export class ArticleSearchService extends ComponentStore<ArticleSearchState> {
const filter = Filter.create(defaultSettings); const filter = Filter.create(defaultSettings);
if (!!defaultQueryParams) { if (defaultQueryParams) {
filter?.fromQueryParams(defaultQueryParams); filter?.fromQueryParams(defaultQueryParams);
} }
@@ -145,7 +145,7 @@ export class ArticleSearchService extends ComponentStore<ArticleSearchState> {
} }
searchRequest(queryToken: QueryTokenDTO) { searchRequest(queryToken: QueryTokenDTO) {
if (!!queryToken?.stockId) { if (queryToken?.stockId) {
return this.catalog.searchWithStockId({ queryToken }); return this.catalog.searchWithStockId({ queryToken });
} else { } else {
return this.catalog.search({ queryToken }); return this.catalog.search({ queryToken });

View File

@@ -65,7 +65,7 @@ export class SearchResultItemComponent extends ComponentStore<SearchResultItemCo
} }
get publicationDate() { get publicationDate() {
if (!!this.item?.product?.publicationDate) { if (this.item?.product?.publicationDate) {
const date = this._dateAdapter.parseDate(this.item.product.publicationDate); const date = this._dateAdapter.parseDate(this.item.product.publicationDate);
if (this._dateAdapter.getDate(date) === 1 && this._dateAdapter.getMonth(date) === 0) { if (this._dateAdapter.getDate(date) === 1 && this._dateAdapter.getMonth(date) === 0) {

View File

@@ -194,7 +194,7 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
} }
const process = await this.application.getProcessById$(processId).pipe(first()).toPromise(); const process = await this.application.getProcessById$(processId).pipe(first()).toPromise();
if (!!process) { if (process) {
await this.updateBreadcrumbs(processId, queryParams); await this.updateBreadcrumbs(processId, queryParams);
await this.createBreadcrumb(processId, queryParams); await this.createBreadcrumb(processId, queryParams);
} }
@@ -223,7 +223,7 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
const ean = this.route?.snapshot?.params?.ean; const ean = this.route?.snapshot?.params?.ean;
// Navigation from Cart uses ean // Navigation from Cart uses ean
if (!!ean) { if (ean) {
await this._navigationService await this._navigationService
.getArticleDetailsPathByEan({ .getArticleDetailsPathByEan({
processId, processId,
@@ -346,7 +346,7 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
} }
search({ filter, clear = false, orderBy = false }: { filter?: Filter; clear?: boolean; orderBy?: boolean }) { search({ filter, clear = false, orderBy = false }: { filter?: Filter; clear?: boolean; orderBy?: boolean }) {
if (!!filter) { if (filter) {
this.sharedFilterInputGroupMain.cancelAutocomplete(); this.sharedFilterInputGroupMain.cancelAutocomplete();
} }
@@ -459,7 +459,7 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
async addToCart(item?: ItemDTO) { async addToCart(item?: ItemDTO) {
this.loading$.next(true); this.loading$.next(true);
if (!!item) { if (item) {
await this.addItemsToCart(item); await this.addItemsToCart(item);
} else { } else {
await this.addItemsToCart(); await this.addItemsToCart();

View File

@@ -316,7 +316,7 @@ export class CheckoutDummyStore extends ComponentStore<CheckoutDummyState> {
quantity, quantity,
availability, availability,
product, product,
promotion: !!item ? { points: promoPoints } : undefined, promotion: item ? { points: promoPoints } : undefined,
destination: { destination: {
data: { target: 1, targetBranch: { id: branch?.id } }, data: { target: 1, targetBranch: { id: branch?.id } },
}, },
@@ -390,7 +390,7 @@ export class CheckoutDummyStore extends ComponentStore<CheckoutDummyState> {
contributors: control.get('contributors').value, contributors: control.get('contributors').value,
manufacturer: control.get('manufacturer').value, manufacturer: control.get('manufacturer').value,
}; };
return !!item return item
? { ? {
catalogProductNumber: String(item.id), catalogProductNumber: String(item.id),
...item.product, ...item.product,

View File

@@ -594,7 +594,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
async patchProcess(processId: number) { async patchProcess(processId: number) {
const process = await this.applicationService.getProcessById$(processId).pipe(first()).toPromise(); const process = await this.applicationService.getProcessById$(processId).pipe(first()).toPromise();
if (!!process) { if (process) {
this.applicationService.patchProcess(process.id, { this.applicationService.patchProcess(process.id, {
name: `${process.name} Bestellbestätigung`, name: `${process.name} Bestellbestätigung`,
type: 'cart-checkout', type: 'cart-checkout',

View File

@@ -57,7 +57,7 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
map(([orders, params]) => { map(([orders, params]) => {
let filteredOrders: DisplayOrderDTO[] = []; let filteredOrders: DisplayOrderDTO[] = [];
if (params?.orderIds) { if (params?.orderIds) {
const orderIds: String[] = params.orderIds.split(','); const orderIds: string[] = params.orderIds.split(',');
filteredOrders = orders.filter((order) => orderIds.find((id) => Number(id) === order.id)); filteredOrders = orders.filter((order) => orderIds.find((id) => Number(id) === order.id));
} else { } else {
return filteredOrders; return filteredOrders;
@@ -68,7 +68,7 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
order.items.find((item) => item.features.orderType !== order.features.orderType), order.items.find((item) => item.features.orderType !== order.features.orderType),
); );
if (!!ordersWithMultipleFeatures) { if (ordersWithMultipleFeatures) {
for (let orderWithMultipleFeatures of ordersWithMultipleFeatures) { for (let orderWithMultipleFeatures of ordersWithMultipleFeatures) {
if (orderWithMultipleFeatures?.items?.length > 1) { if (orderWithMultipleFeatures?.items?.length > 1) {
const itemsWithOrderFeature = orderWithMultipleFeatures.items.filter( const itemsWithOrderFeature = orderWithMultipleFeatures.items.filter(

View File

@@ -138,8 +138,8 @@ export class CustomerOrderDetailsComponent implements OnInit, AfterViewInit, OnD
this._store.processingStatus !== processingStatus this._store.processingStatus !== processingStatus
) { ) {
this._store.patchState({ this._store.patchState({
orderId: !!orderId ? +orderId : undefined, orderId: orderId ? +orderId : undefined,
compartmentCode: !!compartmentCode ? decodeURIComponent(compartmentCode) : undefined, compartmentCode: compartmentCode ? decodeURIComponent(compartmentCode) : undefined,
processingStatus, processingStatus,
}); });
this._store.loadItems(); this._store.loadItems();
@@ -400,7 +400,7 @@ export class CustomerOrderDetailsComponent implements OnInit, AfterViewInit, OnD
await this._navigationService.getCustomerOrdersBasePath(this.processId).navigate(); await this._navigationService.getCustomerOrdersBasePath(this.processId).navigate();
} else { } else {
const item: OrderItemListItemDTO = handler?.orderItemsContext?.items?.find((_) => true); const item: OrderItemListItemDTO = handler?.orderItemsContext?.items?.find((_) => true);
if (!!item) { if (item) {
await this._router.navigate(this.getDetailsPath(item), { await this._router.navigate(this.getDetailsPath(item), {
queryParams: { ...this._activatedRoute.snapshot.queryParams, buyerNumber: item.buyerNumber }, queryParams: { ...this._activatedRoute.snapshot.queryParams, buyerNumber: item.buyerNumber },
}); });

View File

@@ -162,7 +162,7 @@ export class CustomerOrderDetailsStore extends ComponentStore<CustomerOrderDetai
this.select((s) => s.latestCompartmentInfo), this.select((s) => s.latestCompartmentInfo),
]).pipe( ]).pipe(
map(([code, info]) => { map(([code, info]) => {
if (!!info) { if (info) {
return `${code}_${info}`; return `${code}_${info}`;
} }
return code; return code;
@@ -236,7 +236,7 @@ export class CustomerOrderDetailsStore extends ComponentStore<CustomerOrderDetai
const items = res?.result?.filter((item) => { const items = res?.result?.filter((item) => {
return ( return (
item.processingStatus === processingStatus && item.processingStatus === processingStatus &&
(!!buyerNumber ? item.buyerNumber === buyerNumber : true) (buyerNumber ? item.buyerNumber === buyerNumber : true)
); );
}); });
this.patchState({ this.patchState({

View File

@@ -48,7 +48,7 @@ export class CustomerOrderEditComponent implements OnInit {
map(([response, processingStatus, buyerNumber]) => { map(([response, processingStatus, buyerNumber]) => {
return response?.result?.filter( return response?.result?.filter(
(item) => (item) =>
item.processingStatus === +processingStatus && (!!buyerNumber ? item.buyerNumber === buyerNumber : true), item.processingStatus === +processingStatus && (buyerNumber ? item.buyerNumber === buyerNumber : true),
); );
}), }),
tap((items) => this.openModalIfItemsHaveDifferentCustomers(items)), tap((items) => this.openModalIfItemsHaveDifferentCustomers(items)),

View File

@@ -102,7 +102,7 @@ export class CustomerOrderSearchResultsComponent
byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus; byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus;
byCompartmentCodeFn = (item: OrderItemListItemDTO) => byCompartmentCodeFn = (item: OrderItemListItemDTO) =>
!!item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode; item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode;
processId$ = this._activatedRoute.parent.data.pipe(map((data) => +data.processId)); processId$ = this._activatedRoute.parent.data.pipe(map((data) => +data.processId));
@@ -169,7 +169,7 @@ export class CustomerOrderSearchResultsComponent
this._searchResultSubscription.add( this._searchResultSubscription.add(
this._activatedRoute.queryParams.subscribe((queryParams) => { this._activatedRoute.queryParams.subscribe((queryParams) => {
const updateResults = queryParams.updateResults; const updateResults = queryParams.updateResults;
if (!!updateResults) { if (updateResults) {
this.search({ silentReload: true }); this.search({ silentReload: true });
const clean = { ...queryParams }; const clean = { ...queryParams };
delete clean['updateResults']; delete clean['updateResults'];
@@ -247,7 +247,7 @@ export class CustomerOrderSearchResultsComponent
} }
const process = await this._application.getProcessById$(processId).pipe(first()).toPromise(); const process = await this._application.getProcessById$(processId).pipe(first()).toPromise();
if (!!process) { if (process) {
await this.createBreadcrumb(processId, params); await this.createBreadcrumb(processId, params);
await this.updateBreadcrumb(processId, params); await this.updateBreadcrumb(processId, params);
} }
@@ -455,7 +455,7 @@ export class CustomerOrderSearchResultsComponent
silentReload?: boolean; silentReload?: boolean;
clear?: boolean; clear?: boolean;
}) { }) {
if (!!filter) { if (filter) {
this.sharedFilterInputGroupMain.cancelAutocomplete(); this.sharedFilterInputGroupMain.cancelAutocomplete();
this._customerOrderSearchStore.setQueryParams(filter?.getQueryParams()); this._customerOrderSearchStore.setQueryParams(filter?.getQueryParams());
} }

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnInit, ElementRef, ViewChild, Renderer2 } from '@angular/core'; import { Component, ChangeDetectionStrategy, OnInit, ElementRef, ViewChild, Renderer2, AfterViewInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { ApplicationService } from '@core/application'; import { ApplicationService } from '@core/application';
import { AuthService } from '@core/auth'; import { AuthService } from '@core/auth';
@@ -21,7 +21,7 @@ import { provideCancelSearchSubject } from '@shared/services/cancel-subject';
providers: [provideComponentStore(CustomerOrderSearchStore), provideCancelSearchSubject()], providers: [provideComponentStore(CustomerOrderSearchStore), provideCancelSearchSubject()],
standalone: false, standalone: false,
}) })
export class CustomerOrderComponent implements OnInit { export class CustomerOrderComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild(BreadcrumbComponent, { read: ElementRef }) breadcrumbRef: ElementRef<HTMLElement>; @ViewChild(BreadcrumbComponent, { read: ElementRef }) breadcrumbRef: ElementRef<HTMLElement>;
@ViewChild(BranchSelectorComponent, { read: ElementRef }) branchSelectorRef: ElementRef<HTMLElement>; @ViewChild(BranchSelectorComponent, { read: ElementRef }) branchSelectorRef: ElementRef<HTMLElement>;
processId$ = this._activatedRoute.data.pipe(map((data) => String(data.processId))); processId$ = this._activatedRoute.data.pipe(map((data) => String(data.processId)));

View File

@@ -6,7 +6,7 @@
type="text" type="text"
formControlName="street" formControlName="street"
[tabindex]="tabIndexStart" [tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly" [readonly]="readonly"
/> />
</shared-form-control> </shared-form-control>

View File

@@ -6,7 +6,7 @@
type="text" type="text"
[formControl]="control" [formControl]="control"
[tabindex]="tabIndexStart" [tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly" [readonly]="readonly"
/> />
</shared-form-control> </shared-form-control>

View File

@@ -5,7 +5,7 @@
class="input-control" class="input-control"
[formControl]="control" [formControl]="control"
[tabindex]="tabIndexStart" [tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly" [readonly]="readonly"
/> />
</shared-form-control> </shared-form-control>

View File

@@ -6,7 +6,7 @@
type="text" type="text"
formControlName="name" formControlName="name"
[tabindex]="tabIndexStart" [tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly" [readonly]="readonly"
/> />
</shared-form-control> </shared-form-control>

View File

@@ -6,7 +6,7 @@
[formControl]="control" [formControl]="control"
[tabindex]="tabIndexStart" [tabindex]="tabIndexStart"
[readonly]="readonly" [readonly]="readonly"
[autofocus]="focusAfterInit"
/> />
</shared-form-control> </shared-form-control>
<button type="button" *ngIf="!readonly && canScan()" (click)="scan()"> <button type="button" *ngIf="!readonly && canScan()" (click)="scan()">

View File

@@ -6,7 +6,7 @@
type="tel" type="tel"
formControlName="phone" formControlName="phone"
[tabindex]="tabIndexStart" [tabindex]="tabIndexStart"
[autofocus]="focusAfterInit"
[readonly]="readonly" [readonly]="readonly"
/> />
</shared-form-control> </shared-form-control>

View File

@@ -513,7 +513,7 @@ export abstract class AbstractCreateCustomer implements OnInit, OnDestroy {
const response = await this.saveCustomer(customer); const response = await this.saveCustomer(customer);
if (!!response) { if (response) {
this.navigateToCustomerDetails(response); this.navigateToCustomerDetails(response);
} }
} catch (error) { } catch (error) {

View File

@@ -351,7 +351,7 @@ export class CustomerSearchComponent implements OnInit, OnDestroy {
}; };
this._breadcrumbService.addBreadcrumb(breadcrumb); this._breadcrumbService.addBreadcrumb(breadcrumb);
} else if (!!fullName) { } else if (fullName) {
const navigation = this._navigation.detailsRoute({ const navigation = this._navigation.detailsRoute({
processId: this._store.processId, processId: this._store.processId,
customerId: this._store.customerId, customerId: this._store.customerId,

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { Component, ChangeDetectionStrategy, OnDestroy, OnInit, ViewChild, inject, AfterContentInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router'; import { Router, NavigationEnd } from '@angular/router';
import { CustomerSearchStore } from '../store/customer-search.store'; import { CustomerSearchStore } from '../store/customer-search.store';
import { Subscription, BehaviorSubject, combineLatest, Subject, race } from 'rxjs'; import { Subscription, BehaviorSubject, combineLatest, Subject, race } from 'rxjs';
@@ -17,7 +17,7 @@ import { injectCancelSearch } from '@shared/services/cancel-subject';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false, standalone: false,
}) })
export class CustomerResultsSideViewComponent implements OnInit, OnDestroy { export class CustomerResultsSideViewComponent implements OnInit, OnDestroy, AfterContentInit {
private _store = inject(CustomerSearchStore); private _store = inject(CustomerSearchStore);
private _router = inject(Router); private _router = inject(Router);
private _navigation = inject(CustomerSearchNavigation); private _navigation = inject(CustomerSearchNavigation);

View File

@@ -5,7 +5,7 @@ export function genderLastNameValidator(isB2b: boolean): ValidatorFn | null {
return (control: UntypedFormGroup): ValidationErrors | null => { return (control: UntypedFormGroup): ValidationErrors | null => {
const gender = control.get('gender').value; const gender = control.get('gender').value;
const lastName = control.get('lastName').value; const lastName = control.get('lastName').value;
if (!!lastName) { if (lastName) {
control.get('gender').setValidators([Validators.required]); control.get('gender').setValidators([Validators.required]);
return { genderNotSet: true }; return { genderNotSet: true };
} else { } else {

View File

@@ -81,7 +81,7 @@ export class GoodsInCleanupListComponent implements OnInit, OnDestroy {
byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus; byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus;
byCompartmentCodeFn = (item: OrderItemListItemDTO) => byCompartmentCodeFn = (item: OrderItemListItemDTO) =>
!!item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode; item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode;
changeActionLoader$ = new BehaviorSubject<boolean>(false); changeActionLoader$ = new BehaviorSubject<boolean>(false);

View File

@@ -153,7 +153,7 @@ export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComp
this.sscChanged = true; this.sscChanged = true;
const code = (await this.statusCodes$.pipe(first()).toPromise())?.find((statusCode) => statusCode.code === value); const code = (await this.statusCodes$.pipe(first()).toPromise())?.find((statusCode) => statusCode.code === value);
if (!!code) { if (code) {
this.sscText = code.supplierDescription; this.sscText = code.supplierDescription;
this.sscInvalid = false; this.sscInvalid = false;
} else { } else {

View File

@@ -50,7 +50,7 @@ export class GoodsInRemissionPreviewComponent implements OnInit, OnDestroy {
byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus; byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus;
byCompartmentCodeFn = (item: OrderItemListItemDTO) => byCompartmentCodeFn = (item: OrderItemListItemDTO) =>
!!item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode; item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode;
private readonly SCROLL_POSITION_TOKEN = 'REMISSION_PREVIEW_SCROLL_POSITION'; private readonly SCROLL_POSITION_TOKEN = 'REMISSION_PREVIEW_SCROLL_POSITION';

View File

@@ -86,7 +86,7 @@ export class GoodsInReservationComponent implements OnInit, OnDestroy {
byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus; byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus;
byCompartmentCodeFn = (item: OrderItemListItemDTO) => byCompartmentCodeFn = (item: OrderItemListItemDTO) =>
!!item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode; item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode;
constructor( constructor(
private _breadcrumb: BreadcrumbService, private _breadcrumb: BreadcrumbService,
@@ -176,7 +176,7 @@ export class GoodsInReservationComponent implements OnInit, OnDestroy {
if (this._store.hits === 0) { if (this._store.hits === 0) {
this._store.searchResult$.pipe(takeUntil(this._onDestroy$)).subscribe(async (result) => { this._store.searchResult$.pipe(takeUntil(this._onDestroy$)).subscribe(async (result) => {
await this.createBreadcrumb(); await this.createBreadcrumb();
if (!!this._store.searchOptions?.take) { if (this._store.searchOptions?.take) {
this._store.searchOptions = undefined; this._store.searchOptions = undefined;
this.scrollContainer.scrollTo(Number(scroll_position ?? 0)); this.scrollContainer.scrollTo(Number(scroll_position ?? 0));
} }

View File

@@ -39,7 +39,7 @@ export abstract class PickupShelfDetailsBaseComponent {
constructor() { constructor() {
this.activatedRoute.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => { this.activatedRoute.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
// // Fix #4508 - Always Reset Cover Items before fetching new ones inside pickup-shelf-in-details.component // // Fix #4508 - Always Reset Cover Items before fetching new ones inside pickup-shelf-in-details.component
if (!!this.store.coverOrderItems?.length) { if (this.store.coverOrderItems?.length) {
this.store.resetCoverItems(); this.store.resetCoverItems();
} }
this.store.fetchOrder({ orderId: Number(params.orderId) }); this.store.fetchOrder({ orderId: Number(params.orderId) });

View File

@@ -104,7 +104,7 @@ export class PickUpShelfInListComponent implements OnInit, AfterViewInit {
byProcessingStatusFn = (item: DBHOrderItemListItemDTO) => item.processingStatus; byProcessingStatusFn = (item: DBHOrderItemListItemDTO) => item.processingStatus;
byCompartmentCodeFn = (item: DBHOrderItemListItemDTO) => byCompartmentCodeFn = (item: DBHOrderItemListItemDTO) =>
!!item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode; item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode;
trackByFn: TrackByFunction<DBHOrderItemListItemDTO> = (index, item) => trackByFn: TrackByFunction<DBHOrderItemListItemDTO> = (index, item) =>
`${item.orderId}${item.orderItemId}${item.orderItemSubsetId}`; `${item.orderId}${item.orderItemId}${item.orderItemSubsetId}`;

View File

@@ -106,7 +106,7 @@ export class PickupShelfOutDetailsComponent extends PickupShelfDetailsBaseCompon
this.store.setDisableHeaderStatusDropdown(true); this.store.setDisableHeaderStatusDropdown(true);
const context = await this.execAction({ action }); const context = await this.execAction({ action });
if (!!context) { if (context) {
if ( if (
action.command.includes('ARRIVED') || action.command.includes('ARRIVED') ||
action.command.includes('PRINT_PRICEDIFFQRCODELABEL') || action.command.includes('PRINT_PRICEDIFFQRCODELABEL') ||

View File

@@ -121,7 +121,7 @@ export class PickupShelfOutListComponent implements OnInit, AfterViewInit {
byProcessingStatusFn = (item: DBHOrderItemListItemDTO) => item.processingStatus; byProcessingStatusFn = (item: DBHOrderItemListItemDTO) => item.processingStatus;
byCompartmentCodeFn = (item: DBHOrderItemListItemDTO) => byCompartmentCodeFn = (item: DBHOrderItemListItemDTO) =>
!!item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode; item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode;
trackByFn: TrackByFunction<DBHOrderItemListItemDTO> = (index, item) => trackByFn: TrackByFunction<DBHOrderItemListItemDTO> = (index, item) =>
`${item.orderId}${item.orderItemId}${item.orderItemSubsetId}`; `${item.orderId}${item.orderItemId}${item.orderItemSubsetId}`;

View File

@@ -9,7 +9,7 @@ import {
OnInit, OnInit,
Output, Output,
ViewChild, ViewChild,
inject, inject, OnDestroy,
} from '@angular/core'; } from '@angular/core';
import { FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms'; import { FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
import { NavigateOnClickDirective, ProductImageModule } from '@cdn/product-image'; import { NavigateOnClickDirective, ProductImageModule } from '@cdn/product-image';
@@ -63,7 +63,7 @@ export interface PickUpShelfDetailsItemComponentState {
}) })
export class PickUpShelfDetailsItemComponent export class PickUpShelfDetailsItemComponent
extends ComponentStore<PickUpShelfDetailsItemComponentState> extends ComponentStore<PickUpShelfDetailsItemComponentState>
implements OnInit implements OnInit, OnDestroy
{ {
private _store = inject(PickupShelfDetailsStore); private _store = inject(PickupShelfDetailsStore);

View File

@@ -11,7 +11,7 @@ export class PickupShelfCoverCompartmentCodePipe implements PipeTransform {
compartmentCodeSplit.shift(); compartmentCodeSplit.shift();
const compartmentCode = compartmentCodeSplit.join('_'); const compartmentCode = compartmentCodeSplit.join('_');
if (!!item.compartmentInfo) { if (item.compartmentInfo) {
return `${compartmentCode}_${item.compartmentInfo}`; return `${compartmentCode}_${item.compartmentInfo}`;
} }
return compartmentCode; return compartmentCode;

View File

@@ -63,7 +63,7 @@ export class PickupShelfProcessingStatusPipe implements PipeTransform {
}; };
transform(value: OrderItemProcessingStatusValue, color?: boolean): string { transform(value: OrderItemProcessingStatusValue, color?: boolean): string {
return !!color return color
? this.color[value] ? this.color[value]
: ProcessingStatusNameMap.get(value) : ProcessingStatusNameMap.get(value)
? ProcessingStatusNameMap.get(value).value ? ProcessingStatusNameMap.get(value).value

View File

@@ -196,7 +196,7 @@ export class PickupShelfStore extends ComponentStore<PickupShelfState> implement
providerName: this._pickupShelfIOService.name(), providerName: this._pickupShelfIOService.name(),
}); });
if (!!cachedQuerySettings) { if (cachedQuerySettings) {
this.patchState({ fetchingQuerySettings: false, querySettings: cachedQuerySettings }); this.patchState({ fetchingQuerySettings: false, querySettings: cachedQuerySettings });
return false; return false;
} else { } else {
@@ -268,7 +268,7 @@ export class PickupShelfStore extends ComponentStore<PickupShelfState> implement
let list: DBHOrderItemListItemDTO[] = []; let list: DBHOrderItemListItemDTO[] = [];
if (!!cachedListResponse) { if (cachedListResponse) {
this.patchState({ list: cachedListResponse.result, listHits: cachedListResponse.hits }); this.patchState({ list: cachedListResponse.result, listHits: cachedListResponse.hits });
list = cachedListResponse.result; list = cachedListResponse.result;
} else { } else {

View File

@@ -94,7 +94,7 @@ export class RemissionListComponent implements OnInit, OnDestroy {
return false; return false;
} }
if (!!filter?.getQueryToken()?.filter?.abteilungen) { if (filter?.getQueryToken()?.filter?.abteilungen) {
return false; return false;
} }
@@ -186,7 +186,7 @@ export class RemissionListComponent implements OnInit, OnDestroy {
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe((params) => { this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe((params) => {
const id = +params.returnId; const id = +params.returnId;
if (!!id) { if (id) {
// Remission wurde gestartet // Remission wurde gestartet
this._remissionStore.getReturn(id); this._remissionStore.getReturn(id);
} else { } else {
@@ -196,7 +196,7 @@ export class RemissionListComponent implements OnInit, OnDestroy {
}); });
this._remissionStore.getReturnCompleted.pipe(takeUntil(this._onDestroy$)).subscribe((returnDto) => { this._remissionStore.getReturnCompleted.pipe(takeUntil(this._onDestroy$)).subscribe((returnDto) => {
if (!!returnDto) { if (returnDto) {
this._remissionListStore.setSelectedSupplierId(returnDto.supplier.id); this._remissionListStore.setSelectedSupplierId(returnDto.supplier.id);
} }
@@ -213,7 +213,7 @@ export class RemissionListComponent implements OnInit, OnDestroy {
this._onDestroy$.next(); this._onDestroy$.next();
this._onDestroy$.complete(); this._onDestroy$.complete();
if (!!this._remissionStore.return) { if (this._remissionStore.return) {
this._remissionListStore.cacheCurrentData(); this._remissionListStore.cacheCurrentData();
const params = await this._activatedRoute.queryParams.pipe(first()).toPromise(); const params = await this._activatedRoute.queryParams.pipe(first()).toPromise();
await this.updateBreadcrumb(params); await this.updateBreadcrumb(params);

View File

@@ -67,7 +67,7 @@ export class RemissionComponent implements OnInit, OnDestroy {
async updateProcess() { async updateProcess() {
const params = this._activatedRoute.snapshot.firstChild.params; const params = this._activatedRoute.snapshot.firstChild.params;
const queryParams = this._activatedRoute.snapshot.queryParams ?? {}; const queryParams = this._activatedRoute.snapshot.queryParams ?? {};
if (!!params?.returnId) { if (params?.returnId) {
this._applicationService.patchProcess(this.processId, { this._applicationService.patchProcess(this.processId, {
closeable: false, closeable: false,
data: { active: +params.returnId, queryParams }, data: { active: +params.returnId, queryParams },

View File

@@ -73,7 +73,7 @@ export class TaskListComponent {
withLatestFrom(this.selected$), withLatestFrom(this.selected$),
map(([list, date]) => map(([list, date]) =>
list.filter((item) => list.filter((item) =>
!!item?.successor item?.successor
? this.dateAdapter.equals({ ? this.dateAdapter.equals({
first: new Date(item.publicationDate || item.taskDate), first: new Date(item.publicationDate || item.taskDate),
second: date, second: date,
@@ -112,7 +112,7 @@ export class TaskListComponent {
withLatestFrom(this.selected$), withLatestFrom(this.selected$),
map(([list, date]) => map(([list, date]) =>
list.filter((item) => list.filter((item) =>
!!item?.successor item?.successor
? this.dateAdapter.equals({ ? this.dateAdapter.equals({
first: new Date(item.publicationDate || item.taskDate), first: new Date(item.publicationDate || item.taskDate),
second: date, second: date,
@@ -145,7 +145,7 @@ export class TaskListComponent {
withLatestFrom(this.selected$), withLatestFrom(this.selected$),
map(([list, date]) => map(([list, date]) =>
list.filter((item) => list.filter((item) =>
!!item?.successor item?.successor
? this.dateAdapter.equals({ first: new Date(item.publicationDate), second: date, precision: 'day' }) ? this.dateAdapter.equals({ first: new Date(item.publicationDate), second: date, precision: 'day' })
: item, : item,
), ),

View File

@@ -28,3 +28,4 @@
<ui-icon icon="search" size="24px"></ui-icon> <ui-icon icon="search" size="24px"></ui-icon>
</button> </button>
</div> </div>

View File

@@ -1 +0,0 @@
import 'zone.js';

View File

@@ -217,7 +217,7 @@ export class BranchSelectorComponent implements OnInit, OnDestroy, AfterViewInit
} }
emitValues(branch?: BranchDTO) { emitValues(branch?: BranchDTO) {
if (!!branch) { if (branch) {
this.onChange(branch); this.onChange(branch);
this.onTouched(); this.onTouched();
this.valueChange.emit(branch); this.valueChange.emit(branch);

View File

@@ -72,7 +72,7 @@ export class SharedFilterOverlayComponent implements OnInit, OnDestroy {
open() { open() {
const dropdownPortal = new TemplatePortal(this.filterOverlay, this._viewContainerRef); const dropdownPortal = new TemplatePortal(this.filterOverlay, this._viewContainerRef);
if (!!this.viewRef) { if (this.viewRef) {
this.close(); this.close();
} }

View File

@@ -200,7 +200,7 @@ export class Filter implements IFilter {
?.map((i) => i.toStringValue()) ?.map((i) => i.toStringValue())
?.filter((i) => !!i) ?.filter((i) => !!i)
?.join(';'); ?.join(';');
if (!!value) { if (value) {
filter[key] = value; filter[key] = value;
} }
} else { } else {
@@ -211,7 +211,7 @@ export class Filter implements IFilter {
?.map((i) => i.toStringValue()) ?.map((i) => i.toStringValue())
?.filter((i) => !!i) ?.filter((i) => !!i)
?.join(';'); ?.join(';');
if (!!value) { if (value) {
filter[key] = value; filter[key] = value;
} }
} }
@@ -257,7 +257,7 @@ export class Filter implements IFilter {
queryParams['main_qs'] = queryToken.input.qs; queryParams['main_qs'] = queryToken.input.qs;
} }
if (!!queryToken.filter) { if (queryToken.filter) {
for (const key in queryToken.filter) { for (const key in queryToken.filter) {
queryParams[`filter_${key}`] = queryToken.filter[key]; queryParams[`filter_${key}`] = queryToken.filter[key];
} }

View File

@@ -92,7 +92,7 @@ export class Option implements IOption {
getParentInputOptions() { getParentInputOptions() {
let parent = this.parent; let parent = this.parent;
while (!!parent) { while (parent) {
if (parent instanceof InputOptions) { if (parent instanceof InputOptions) {
return parent; return parent;
} }

View File

@@ -5,7 +5,7 @@ export class EmptyControl extends AbstractControl {
super([], []); super([], []);
} }
setValue(value: any, options?: Object): void {} setValue(value: any, options?: object): void {}
patchValue(value: any, options?: Object): void {} patchValue(value: any, options?: object): void {}
reset(value?: any, options?: Object): void {} reset(value?: any, options?: object): void {}
} }

View File

@@ -259,7 +259,7 @@ export class SharedGoodsInOutOrderDetailsItemComponent
.pipe(takeUntil(this._onDestroy$), take(1)) .pipe(takeUntil(this._onDestroy$), take(1))
.toPromise(); .toPromise();
if (!!history) { if (history) {
if (history.length > 0) { if (history.length > 0) {
const data: HistoryData = { const data: HistoryData = {
customerName, customerName,

View File

@@ -107,7 +107,7 @@ export abstract class SharedGoodsInOutOrderDetailsStore
this.select((s) => s.latestCompartmentInfo), this.select((s) => s.latestCompartmentInfo),
]).pipe( ]).pipe(
map(([code, info]) => { map(([code, info]) => {
if (!!info) { if (info) {
return `${code}_${info}`; return `${code}_${info}`;
} }
return code; return code;
@@ -141,7 +141,7 @@ export abstract class SharedGoodsInOutOrderDetailsStore
if ( if (
coverItems.find((i) => { coverItems.find((i) => {
let compartmentCode = i.compartmentCode; let compartmentCode = i.compartmentCode;
if (!!i.compartmentInfo) { if (i.compartmentInfo) {
compartmentCode = `${i.compartmentCode}_${i.compartmentInfo}`; compartmentCode = `${i.compartmentCode}_${i.compartmentInfo}`;
} }

View File

@@ -11,7 +11,7 @@ export class CoverCompartmentCodePipe implements PipeTransform {
compartmentCodeSplit.shift(); compartmentCodeSplit.shift();
const compartmentCode = compartmentCodeSplit.join('_'); const compartmentCode = compartmentCodeSplit.join('_');
if (!!item.compartmentInfo) { if (item.compartmentInfo) {
return `${compartmentCode}_${item.compartmentInfo}`; return `${compartmentCode}_${item.compartmentInfo}`;
} }
return compartmentCode; return compartmentCode;

View File

@@ -166,7 +166,7 @@ export class SharedNotificationChannelControlComponent
// Ticket #4526 RD // Bearbeiten - erneut senden Button fehlt // Ticket #4526 RD // Bearbeiten - erneut senden Button fehlt
// Auf den Pickup Shelf Edit Seiten soll der Erneut senden button immer ersichtlich sein // Auf den Pickup Shelf Edit Seiten soll der Erneut senden button immer ersichtlich sein
showSendAgainActionForEmail() { showSendAgainActionForEmail() {
return this.channelActionName === 'Erneut senden' && (this.getNotificationChannel() as Number) !== 3; return this.channelActionName === 'Erneut senden' && (this.getNotificationChannel() as number) !== 3;
} }
// Ticket #4526 RD // Bearbeiten - erneut senden Button fehlt // Ticket #4526 RD // Bearbeiten - erneut senden Button fehlt

View File

@@ -169,7 +169,7 @@ export class SearchboxComponent
} }
startScan() { startScan() {
if (!!this.scanAdapterService?.isReady()) { if (this.scanAdapterService?.isReady()) {
this.subscriptions.add( this.subscriptions.add(
this.scanAdapterService.scan().subscribe((result) => { this.scanAdapterService.scan().subscribe((result) => {
this.scan.emit(result); this.scan.emit(result);

View File

@@ -1,4 +1,4 @@
import { ChangeDetectorRef, Pipe, PipeTransform, OnDestroy } from '@angular/core'; import { ChangeDetectorRef, Pipe, PipeTransform, OnDestroy, OnInit } from '@angular/core';
import { BranchService, BranchDTO } from '@generated/swagger/oms-api'; import { BranchService, BranchDTO } from '@generated/swagger/oms-api';
import { memorize } from '@utils/common'; import { memorize } from '@utils/common';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@@ -9,7 +9,7 @@ import { shareReplay, takeUntil } from 'rxjs/operators';
standalone: true, standalone: true,
pure: false, pure: false,
}) })
export class ResolveBranchPipe implements PipeTransform, OnDestroy { export class ResolveBranchPipe implements PipeTransform, OnDestroy, OnInit {
value: BranchDTO | undefined; value: BranchDTO | undefined;
private _onDestroy$ = new Subject<void>(); private _onDestroy$ = new Subject<void>();

View File

@@ -42,7 +42,7 @@ export class ShellProcessBarItemComponent implements OnInit, OnDestroy, OnChange
routerLink$: Observable<string[] | any[]> = NEVER; routerLink$: Observable<string[] | any[]> = NEVER;
queryParams$: Observable<Object> = NEVER; queryParams$: Observable<object> = NEVER;
isActive$: Observable<boolean> = NEVER; isActive$: Observable<boolean> = NEVER;

View File

@@ -0,0 +1,6 @@
import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
setupZoneTestEnv({
errorOnUnknownElements: true,
errorOnUnknownProperties: true,
});

View File

@@ -95,7 +95,7 @@ export class UiBranchDropdownComponent implements OnChanges {
setFilteredBranches(filterValue?: string) { setFilteredBranches(filterValue?: string) {
const branches = [...this.branches]; const branches = [...this.branches];
const currentBranch = branches.find((b) => b.name === this.selected); const currentBranch = branches.find((b) => b.name === this.selected);
if (!!filterValue) { if (filterValue) {
const filterResult = branches.filter((b) => { const filterResult = branches.filter((b) => {
const name = b.name.toLowerCase(); const name = b.name.toLowerCase();
const zipCode = b.address?.zipCode; const zipCode = b.address?.zipCode;

View File

@@ -201,8 +201,8 @@ export class DateAdapter {
findClosestDate(a: Date, b: Date, compareDate?: Date) { findClosestDate(a: Date, b: Date, compareDate?: Date) {
const date = compareDate || this.today(); const date = compareDate || this.today();
var distancea = Math.abs(date.getTime() - a.getTime()); let distancea = Math.abs(date.getTime() - a.getTime());
var distanceb = Math.abs(date.getTime() - b.getTime()); let distanceb = Math.abs(date.getTime() - b.getTime());
return distancea - distanceb; return distancea - distanceb;
} }

View File

@@ -113,7 +113,7 @@ export class UiOverlayTriggerDirective implements OnInit, OnDestroy, OnChanges {
open() { open() {
const dropdownPortal = new TemplatePortal(this.component.templateRef, this.viewContainerRef); const dropdownPortal = new TemplatePortal(this.component.templateRef, this.viewContainerRef);
if (!!this.viewRef) { if (this.viewRef) {
this.close(); this.close();
} }

View File

@@ -62,7 +62,7 @@ export class ScrollPositionService {
scrollToLastRememberedPosition(elementRef: ElementRef<any>) { scrollToLastRememberedPosition(elementRef: ElementRef<any>) {
// Skip initial call // Skip initial call
if (!!this.scrollPosition) { if (this.scrollPosition) {
elementRef.nativeElement.scrollTo(0, this.scrollPosition); elementRef.nativeElement.scrollTo(0, this.scrollPosition);
} }
} }

View File

@@ -74,8 +74,8 @@ export class UiDatepickerCellDirective implements OnInit, OnDestroy {
initRange$() { initRange$() {
const sub = combineLatest([this.dateSubject, this.datepicker.min$, this.datepicker.max$]).subscribe( const sub = combineLatest([this.dateSubject, this.datepicker.min$, this.datepicker.max$]).subscribe(
([date, min, max]) => { ([date, min, max]) => {
const minInRange = !!min ? this.dateAdapter.compareDate(date, min) > 0 : true; const minInRange = min ? this.dateAdapter.compareDate(date, min) > 0 : true;
const maxInRange = !!max ? this.dateAdapter.compareDate(max, date) > 0 : true; const maxInRange = max ? this.dateAdapter.compareDate(max, date) > 0 : true;
this.inRange = minInRange && maxInRange; this.inRange = minInRange && maxInRange;
this.notInRange = !this.inRange; this.notInRange = !this.inRange;

View File

@@ -126,7 +126,7 @@ export abstract class Datepicker {
} }
setMin(date: Date) { setMin(date: Date) {
if (!!!date && !this.dateAdapter.isValid(date)) { if (!date && !this.dateAdapter.isValid(date)) {
throw new Error('Date is not Valid.'); throw new Error('Date is not Valid.');
} }
@@ -134,7 +134,7 @@ export abstract class Datepicker {
} }
setMax(date: Date) { setMax(date: Date) {
if (!!!date && !this.dateAdapter.isValid(date)) { if (!date && !this.dateAdapter.isValid(date)) {
throw new Error('Date is not Valid.'); throw new Error('Date is not Valid.');
} }

View File

@@ -160,7 +160,7 @@ export class UiFilter implements IUiFilter {
?.map((i) => i.toStringValue()) ?.map((i) => i.toStringValue())
?.filter((i) => !!i) ?.filter((i) => !!i)
?.join(';'); ?.join(';');
if (!!value) { if (value) {
filter[key] = value; filter[key] = value;
} }
} else { } else {
@@ -171,7 +171,7 @@ export class UiFilter implements IUiFilter {
?.map((i) => i.toStringValue()) ?.map((i) => i.toStringValue())
?.filter((i) => !!i) ?.filter((i) => !!i)
?.join(';'); ?.join(';');
if (!!value) { if (value) {
filter[key] = value; filter[key] = value;
} }
} }
@@ -223,7 +223,7 @@ export class UiFilter implements IUiFilter {
queryParams['main_qs'] = queryToken.input.qs; queryParams['main_qs'] = queryToken.input.qs;
} }
if (!!queryToken.filter) { if (queryToken.filter) {
for (const key in queryToken.filter) { for (const key in queryToken.filter) {
queryParams[`filter_${key}`] = queryToken.filter[key]; queryParams[`filter_${key}`] = queryToken.filter[key];
} }

View File

@@ -42,7 +42,7 @@ export class UiDateInputDirective extends UiFormControlDirective<any> implements
} }
writeValue(obj: string | Date): void { writeValue(obj: string | Date): void {
if (!!obj) { if (obj) {
this.setValue(new Date(obj), false); this.setValue(new Date(obj), false);
} else { } else {
this.setValue('', false); this.setValue('', false);
@@ -80,7 +80,7 @@ export class UiDateInputDirective extends UiFormControlDirective<any> implements
} }
getDateStruct(stringDate: string): { date: number; month: number; year: number } | undefined { getDateStruct(stringDate: string): { date: number; month: number; year: number } | undefined {
if (!!stringDate) { if (stringDate) {
const parts = stringDate.trim().split('.'); const parts = stringDate.trim().split('.');
if (parts.length === 3) { if (parts.length === 3) {
const date = +parts[0]; const date = +parts[0];

View File

@@ -16,7 +16,7 @@ export class UiLoaderComponent implements IUiLoader {
@Input('uiLoader') @Input('uiLoader')
loading: boolean = false; loading: boolean = false;
@Input('spinnerSize') @Input()
spinnerSize: string = '36px'; spinnerSize: string = '36px';
constructor() {} constructor() {}
@@ -34,7 +34,7 @@ export class UiButtonLoaderComponent implements IUiLoader {
@HostBinding('disabled') @HostBinding('disabled')
loading: boolean = false; loading: boolean = false;
@Input('spinnerSize') @Input()
spinnerSize: string = '1em'; spinnerSize: string = '1em';
constructor() {} constructor() {}

View File

@@ -172,7 +172,7 @@ export class UiSearchboxNextComponent
} }
startScan() { startScan() {
if (!!this.scanAdapterService?.isReady()) { if (this.scanAdapterService?.isReady()) {
this.subscriptions.add( this.subscriptions.add(
this.scanAdapterService.scan().subscribe((result) => { this.scanAdapterService.scan().subscribe((result) => {
this.scan.emit(result); this.scan.emit(result);

View File

@@ -2,7 +2,7 @@ import { DebounceSettings, debounce as lodashDebounce } from 'lodash';
export function debounce(wait: number, options?: DebounceSettings): MethodDecorator { export function debounce(wait: number, options?: DebounceSettings): MethodDecorator {
return ( return (
target: Object, target: object,
propertyKey: string, propertyKey: string,
descriptor: TypedPropertyDescriptor<any>, descriptor: TypedPropertyDescriptor<any>,
): TypedPropertyDescriptor<any> => { ): TypedPropertyDescriptor<any> => {

View File

@@ -1,15 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{ {
"extends": "../../tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../../out-tsc/app", "outDir": "../../dist/out-tsc",
"types": [] "types": []
}, },
"files": [ "files": ["src/main.ts"],
"src/main.ts", "include": ["src/**/*.d.ts"],
"src/polyfills.ts" "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
],
"include": [
"src/**/*.d.ts"
]
} }

View File

@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"include": ["src/**/*.ts"],
"compilerOptions": {},
"exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
}

View File

@@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "es2022",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": false,
"strict": false,
"noImplicitOverride": false,
"noPropertyAccessFromIndexSignature": false,
"noImplicitReturns": false,
"noFallthroughCasesInSwitch": false,
"useDefineForClassFields": false,
"resolveJsonModule": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.editor.json"
},
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../tsconfig.base.json",
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}

View File

@@ -1,14 +1,16 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{ {
"extends": "../../tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../../out-tsc/spec", "outDir": "../../dist/out-tsc",
"types": [ "module": "commonjs",
"jasmine" "target": "es2016",
] "types": ["jest", "node"]
}, },
"files": ["src/test-setup.ts"],
"include": [ "include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts", "src/**/*.spec.ts",
"src/**/*.d.ts" "src/**/*.d.ts"
] ]
} }

20
nx.json
View File

@@ -39,6 +39,11 @@
"cache": true, "cache": true,
"dependsOn": ["^build"], "dependsOn": ["^build"],
"inputs": ["production", "^production"] "inputs": ["production", "^production"]
},
"@angular-devkit/build-angular:application": {
"cache": true,
"dependsOn": ["^build"],
"inputs": ["production", "^production"]
} }
}, },
"defaultBase": "develop", "defaultBase": "develop",
@@ -64,6 +69,12 @@
}, },
"@nx/angular:component": { "@nx/angular:component": {
"style": "css" "style": "css"
},
"@nx/angular:application": {
"e2eTestRunner": "none",
"linter": "eslint",
"style": "css",
"unitTestRunner": "jest"
} }
}, },
"plugins": [ "plugins": [
@@ -72,6 +83,15 @@
"options": { "options": {
"targetName": "eslint:lint" "targetName": "eslint:lint"
} }
},
{
"plugin": "@nx/storybook/plugin",
"options": {
"serveStorybookTargetName": "storybook",
"buildStorybookTargetName": "build-storybook",
"testStorybookTargetName": "test-storybook",
"staticStorybookTargetName": "static-storybook"
}
} }
] ]
} }

865
package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -60,6 +60,7 @@
"@angular/cli": "^19.1.8", "@angular/cli": "^19.1.8",
"@angular/compiler-cli": "19.1.7", "@angular/compiler-cli": "19.1.7",
"@angular/language-service": "19.1.7", "@angular/language-service": "19.1.7",
"@angular/pwa": "^19.2.0",
"@eslint/js": "^9.8.0", "@eslint/js": "^9.8.0",
"@ngneat/spectator": "^19.0.0", "@ngneat/spectator": "^19.0.0",
"@ngrx/signals": "^19.0.1", "@ngrx/signals": "^19.0.1",
@@ -68,6 +69,8 @@
"@nx/eslint-plugin": "20.4.6", "@nx/eslint-plugin": "20.4.6",
"@nx/jest": "20.4.6", "@nx/jest": "20.4.6",
"@nx/js": "20.4.6", "@nx/js": "20.4.6",
"@nx/storybook": "^20.4.6",
"@nx/web": "20.4.6",
"@nx/workspace": "20.4.6", "@nx/workspace": "20.4.6",
"@schematics/angular": "^19.1.8", "@schematics/angular": "^19.1.8",
"@softarc/eslint-plugin-sheriff": "^0.18.0", "@softarc/eslint-plugin-sheriff": "^0.18.0",
@@ -77,6 +80,7 @@
"@swc/helpers": "~0.5.11", "@swc/helpers": "~0.5.11",
"@types/jasmine": "~5.1.4", "@types/jasmine": "~5.1.4",
"@types/jest": "^29.5.12", "@types/jest": "^29.5.12",
"@types/lodash": "^4.17.16",
"@types/node": "18.16.9", "@types/node": "18.16.9",
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"@typescript-eslint/utils": "^8.19.0", "@typescript-eslint/utils": "^8.19.0",
@@ -105,6 +109,7 @@
"postcss": "^8.5.3", "postcss": "^8.5.3",
"prettier": "^3.5.2", "prettier": "^3.5.2",
"pretty-quick": "~4.0.0", "pretty-quick": "~4.0.0",
"storybook": "^8.4.6",
"tailwindcss": "^3.4.14", "tailwindcss": "^3.4.14",
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",
"ts-node": "10.9.1", "ts-node": "10.9.1",