mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Compare commits
21 Commits
hotfix/453
...
fix/4534-P
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16b047f2da | ||
|
|
6feb8079b7 | ||
|
|
7f8f48f393 | ||
|
|
0fe0c5242d | ||
|
|
d208bdaf97 | ||
|
|
dc80df4ad4 | ||
|
|
3020609682 | ||
|
|
5c3e1ed2ad | ||
|
|
e832feebc5 | ||
|
|
08580d782d | ||
|
|
2d07556341 | ||
|
|
9ad1256019 | ||
|
|
250002f057 | ||
|
|
0973b01bf0 | ||
|
|
d5254cc150 | ||
|
|
adc5a5a280 | ||
|
|
f0b653fd0f | ||
|
|
14eba6e5ea | ||
|
|
5073693fc2 | ||
|
|
f3cb6236a5 | ||
|
|
4ab9890313 |
@@ -40,8 +40,9 @@
|
||||
|
||||
<div class="page-search-results__order-by mb-[0.125rem]" [class.page-search-results__order-by-primary]="primaryOutletActive$ | async">
|
||||
<shared-order-by-filter
|
||||
[orderBy]="(filter$ | async)?.orderBy"
|
||||
(selectedOrderByChange)="search({ clear: true, orderBy: true }); updateBreadcrumbs()"
|
||||
*ngIf="filter$ | async; let filter"
|
||||
[orderBy]="filter?.orderBy"
|
||||
(selectedOrderByChange)="search({ filter, clear: true, orderBy: true }); updateBreadcrumbs()"
|
||||
>
|
||||
</shared-order-by-filter>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
AfterViewInit,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
@@ -20,7 +20,7 @@ import { ItemDTO } from '@swagger/cat';
|
||||
import { AddToShoppingCartDTO } from '@swagger/checkout';
|
||||
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
|
||||
import { CacheService } from 'apps/core/cache/src/public-api';
|
||||
import { debounce, isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash';
|
||||
import { BehaviorSubject, combineLatest, Subscription } from 'rxjs';
|
||||
import { debounceTime, first, map, switchMap, withLatestFrom } from 'rxjs/operators';
|
||||
import { ArticleSearchService } from '../article-search.store';
|
||||
@@ -115,7 +115,8 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
|
||||
private _checkoutService: DomainCheckoutService,
|
||||
private _environment: EnvironmentService,
|
||||
private _navigationService: ProductCatalogNavigationService,
|
||||
private _availability: DomainAvailabilityService
|
||||
private _availability: DomainAvailabilityService,
|
||||
private _router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -198,9 +199,9 @@ export class ArticleSearchResultsComponent implements OnInit, OnDestroy, AfterVi
|
||||
.subscribe(async ([searchCompleted, processId]) => {
|
||||
const params = searchCompleted.state.filter.getQueryParams();
|
||||
if (searchCompleted.state.searchState === '') {
|
||||
// Keine Navigation bei OrderBy
|
||||
// Ticket 4524 Korrekte Navigation bei orderBy mit aktuellen queryParams
|
||||
if (searchCompleted?.orderBy) {
|
||||
return;
|
||||
return await this._router.navigate([], { queryParams: params });
|
||||
}
|
||||
|
||||
// Navigation auf Details bzw. Results | Details wenn hits 1
|
||||
|
||||
@@ -81,8 +81,11 @@
|
||||
*ngIf="group?.orderType !== undefined && (item.features?.orderType === 'Abholung' || item.features?.orderType === 'Rücklage')"
|
||||
>
|
||||
<ng-container *ngIf="item?.destination?.data?.targetBranch?.data; let targetBranch">
|
||||
<ng-container *ngIf="i === 0 || targetBranch.id !== group.items[i - 1].destination?.data?.targetBranch?.data.id">
|
||||
<div class="flex flex-row items-center px-5 pt-0 pb-[0.875rem] -mt-2 bg-[#F5F7FA]">
|
||||
<ng-container *ngIf="i === 0 || checkIfMultipleDestinationsForOrderTypeExist(targetBranch, group, i)">
|
||||
<div
|
||||
class="flex flex-row items-center px-5 pt-0 pb-[0.875rem] -mt-2 bg-[#F5F7FA]"
|
||||
[class.multiple-destinations]="checkIfMultipleDestinationsForOrderTypeExist(targetBranch, group, i)"
|
||||
>
|
||||
<span class="branch-name">{{ targetBranch?.name }} | {{ targetBranch | branchAddress }}</span>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
@@ -105,6 +105,10 @@ h1 {
|
||||
}
|
||||
}
|
||||
|
||||
.multiple-destinations {
|
||||
@apply py-[0.875rem] mt-0;
|
||||
}
|
||||
|
||||
.icon-order-type {
|
||||
@apply text-black mr-2;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Router } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { DomainAvailabilityService } from '@domain/availability';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { AvailabilityDTO, DestinationDTO, ShoppingCartItemDTO } from '@swagger/checkout';
|
||||
import { AvailabilityDTO, BranchDTO, DestinationDTO, ShoppingCartItemDTO } from '@swagger/checkout';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { PrintModalData, PrintModalComponent } from '@modal/printer';
|
||||
import { delay, first, map, switchMap, takeUntil, tap } from 'rxjs/operators';
|
||||
@@ -254,6 +254,10 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
|
||||
});
|
||||
}
|
||||
|
||||
checkIfMultipleDestinationsForOrderTypeExist(targetBranch: BranchDTO, group: { items: ShoppingCartItemDTO[] }, i: number) {
|
||||
return i === 0 ? false : targetBranch.id !== group.items[i - 1].destination?.data?.targetBranch?.data.id;
|
||||
}
|
||||
|
||||
async refreshAvailabilities() {
|
||||
this.checkingOla$.next(true);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Filter } from '@shared/components/filter';
|
||||
import { BranchDTO, ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO, QuerySettingsDTO } from '@swagger/oms';
|
||||
import { isResponseArgs } from '@utils/object';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { switchMap, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
export interface CustomerOrderSearchState {
|
||||
defaultSettings?: QuerySettingsDTO;
|
||||
@@ -125,6 +125,8 @@ export class CustomerOrderSearchStore extends ComponentStore<CustomerOrderSearch
|
||||
|
||||
searchStarted = new Subject<{ clear?: boolean; silentReload?: boolean }>();
|
||||
|
||||
cancelSearch$ = new Subject<void>();
|
||||
|
||||
constructor(private _domainGoodsInService: DomainCustomerOrderService, private _cache: CacheService) {
|
||||
super({
|
||||
fetching: false,
|
||||
@@ -192,6 +194,11 @@ export class CustomerOrderSearchStore extends ComponentStore<CustomerOrderSearch
|
||||
});
|
||||
}
|
||||
|
||||
cancelSearchRequest() {
|
||||
this.cancelSearch$.next();
|
||||
this.patchState({ fetching: false, silentFetching: false });
|
||||
}
|
||||
|
||||
search = this.effect((options$: Observable<{ clear?: boolean; siletReload?: boolean }>) =>
|
||||
options$.pipe(
|
||||
tap((_) => {
|
||||
@@ -238,6 +245,7 @@ export class CustomerOrderSearchStore extends ComponentStore<CustomerOrderSearch
|
||||
}
|
||||
|
||||
return this._domainGoodsInService.search(queryToken).pipe(
|
||||
takeUntil(this.cancelSearch$),
|
||||
tapResponse(
|
||||
(res) => {
|
||||
let _results: OrderItemListItemDTO[] = [];
|
||||
|
||||
@@ -17,10 +17,7 @@ import { ApplicationService } from '@core/application';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CustomerOrderSearchMainComponent implements OnInit, OnDestroy {
|
||||
filter$ = this._customerOrderSearchStore.filter$.pipe(
|
||||
filter((f) => !!f),
|
||||
take(1)
|
||||
);
|
||||
filter$ = this._customerOrderSearchStore.filter$.pipe(filter((f) => !!f));
|
||||
|
||||
loading$ = this._customerOrderSearchStore.fetching$;
|
||||
|
||||
|
||||
@@ -170,10 +170,9 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
);
|
||||
|
||||
this._searchResultSubscription.add(
|
||||
this.processId$
|
||||
combineLatest([this.processId$, this._activatedRoute.queryParams])
|
||||
.pipe(
|
||||
debounceTime(150),
|
||||
withLatestFrom(this._activatedRoute.queryParams),
|
||||
switchMap(([processId, params]) =>
|
||||
this._application.getSelectedBranch$(processId).pipe(map((selectedBranch) => ({ processId, params, selectedBranch })))
|
||||
)
|
||||
@@ -185,16 +184,6 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
|
||||
if (processChanged) {
|
||||
if (!!this._customerOrderSearchStore.processId && this._customerOrderSearchStore.filter instanceof Filter) {
|
||||
const queryToken = {
|
||||
...this._customerOrderSearchStore.filter?.getQueryParams(),
|
||||
processId,
|
||||
branchId: String(selectedBranch?.id),
|
||||
};
|
||||
this._customerOrderSearchStore.setCache({
|
||||
queryToken,
|
||||
hits: this._customerOrderSearchStore.hits,
|
||||
results: this._customerOrderSearchStore.results,
|
||||
});
|
||||
await this.updateBreadcrumb(processId, this._customerOrderSearchStore.filter?.getQueryParams());
|
||||
}
|
||||
this._customerOrderSearchStore.patchState({ processId });
|
||||
@@ -212,6 +201,7 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
|
||||
if (!isEqual(cleanQueryParams, this.cleanupQueryParams(this._customerOrderSearchStore.filter.getQueryParams()))) {
|
||||
this._customerOrderSearchStore.setQueryParams(params);
|
||||
|
||||
const queryToken = {
|
||||
...this._customerOrderSearchStore.filter.getQueryParams(),
|
||||
processId,
|
||||
@@ -246,8 +236,8 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
|
||||
const process = await this._application.getProcessById$(processId).pipe(first()).toPromise();
|
||||
if (!!process) {
|
||||
await this.updateBreadcrumb(processId, params);
|
||||
await this.createBreadcrumb(processId, params);
|
||||
await this.updateBreadcrumb(processId, params);
|
||||
}
|
||||
|
||||
if (this._activatedRoute?.outlet === 'primary') {
|
||||
@@ -288,13 +278,13 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
...this.cleanupQueryParams(this._customerOrderSearchStore?.filter?.getQueryParams()),
|
||||
main_qs: this.sharedFilterInputGroupMain?.uiInput?.value,
|
||||
};
|
||||
|
||||
this._customerOrderSearchStore?.setQueryParams(queryParams);
|
||||
})
|
||||
);
|
||||
|
||||
this._router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
|
||||
if (event instanceof NavigationStart) {
|
||||
this.cacheResults();
|
||||
this._addScrollPositionToCache();
|
||||
}
|
||||
});
|
||||
@@ -335,18 +325,6 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
this._onDestroy$.complete();
|
||||
|
||||
this._searchResultSubscription.unsubscribe();
|
||||
|
||||
const queryToken = {
|
||||
...this._customerOrderSearchStore.filter?.getQueryParams(),
|
||||
processId: this._customerOrderSearchStore.processId,
|
||||
branchId: String(this._customerOrderSearchStore.selectedBranch?.id),
|
||||
};
|
||||
this._customerOrderSearchStore.setCache({
|
||||
queryToken,
|
||||
hits: this._customerOrderSearchStore.hits,
|
||||
results: this._customerOrderSearchStore.results,
|
||||
});
|
||||
|
||||
await this.updateBreadcrumb(this._customerOrderSearchStore.processId, this._customerOrderSearchStore.filter?.getQueryParams());
|
||||
}
|
||||
|
||||
@@ -364,25 +342,6 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
return clean;
|
||||
}
|
||||
|
||||
async removeBreadcrumbs(processId: number) {
|
||||
const editCrumbs = await this._breadcrumb.getBreadcrumbsByKeyAndTags$(processId, ['customer-order', 'edit']).pipe(first()).toPromise();
|
||||
|
||||
const historyCrumbs = await this._breadcrumb
|
||||
.getBreadcrumbsByKeyAndTags$(processId, ['customer-order', 'history'])
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
editCrumbs.forEach((crumb) => {
|
||||
this._breadcrumb.removeBreadcrumb(crumb.id, true);
|
||||
});
|
||||
|
||||
historyCrumbs.forEach((crumb) => {
|
||||
this._breadcrumb.removeBreadcrumb(crumb.id, true);
|
||||
});
|
||||
|
||||
await this.removeDetailsBreadcrumb(processId);
|
||||
}
|
||||
|
||||
async removeDetailsBreadcrumb(processId: number) {
|
||||
const detailsCrumbs = await this._breadcrumb
|
||||
.getBreadcrumbsByKeyAndTags$(processId, ['customer-order', 'details'])
|
||||
@@ -394,7 +353,19 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
});
|
||||
}
|
||||
|
||||
async createMainBreadcrumb(processId: number, params: Record<string, string>) {
|
||||
await this._breadcrumb.addBreadcrumbIfNotExists({
|
||||
key: processId,
|
||||
name: 'Kundenbestellung',
|
||||
path: this._navigationService.getCustomerOrdersBasePath(processId).path,
|
||||
params,
|
||||
tags: ['customer-order', 'main', 'filter'],
|
||||
section: 'customer',
|
||||
});
|
||||
}
|
||||
|
||||
async createBreadcrumb(processId: number, params: Record<string, string>) {
|
||||
await this.createMainBreadcrumb(processId, params);
|
||||
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
|
||||
key: processId,
|
||||
name: this.getBreadcrumbName(params),
|
||||
@@ -423,6 +394,20 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
}
|
||||
}
|
||||
|
||||
cacheResults() {
|
||||
const queryToken = {
|
||||
...this._customerOrderSearchStore.filter?.getQueryParams(),
|
||||
processId: this._customerOrderSearchStore.processId,
|
||||
branchId: String(this._customerOrderSearchStore.selectedBranch?.id),
|
||||
};
|
||||
|
||||
this._customerOrderSearchStore.setCache({
|
||||
queryToken,
|
||||
hits: this._customerOrderSearchStore.hits,
|
||||
results: this._customerOrderSearchStore.results,
|
||||
});
|
||||
}
|
||||
|
||||
getBreadcrumbName(params: Record<string, string>) {
|
||||
const input = params?.main_qs;
|
||||
|
||||
@@ -442,8 +427,8 @@ export class CustomerOrderSearchResultsComponent extends ComponentStore<Customer
|
||||
search({ filter, clear = false }: { filter?: Filter; clear?: boolean }) {
|
||||
if (!!filter) {
|
||||
this.sharedFilterInputGroupMain.cancelAutocomplete();
|
||||
this._customerOrderSearchStore.setQueryParams(filter?.getQueryParams());
|
||||
}
|
||||
|
||||
this._customerOrderSearchStore.search({ clear });
|
||||
}
|
||||
|
||||
|
||||
@@ -42,13 +42,24 @@ export class CustomerOrderComponent implements OnInit {
|
||||
private _uiModal: UiModalService,
|
||||
private _renderer: Renderer2,
|
||||
private _environmentService: EnvironmentService,
|
||||
public auth: AuthService
|
||||
public auth: AuthService,
|
||||
private _store: CustomerOrderSearchStore
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.selectedBranch$ = this.application.activatedProcessId$.pipe(
|
||||
switchMap((processId) => this.application.getSelectedBranch$(Number(processId)))
|
||||
);
|
||||
|
||||
/* Ticket #4544 - Suchrequest abbrechen bei Prozesswechsel
|
||||
/ um zu verhindern, dass die Suche in einen anderen Kundenbestellungen Prozess übernommen wird
|
||||
/ bei Prozesswechsel zwischen 2 Kundenbestellungen Prozessen
|
||||
*/
|
||||
this.processId$.pipe(takeUntil(this._onDestroy$)).subscribe((processId) => {
|
||||
if (Number(processId) !== this._store.processId) {
|
||||
this._store.cancelSearchRequest();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { CrmCustomerService } from '@domain/crm';
|
||||
import { AddressDTO, CustomerDTO, CustomerInfoDTO, PayerDTO, ShippingAddressDTO } from '@swagger/crm';
|
||||
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
|
||||
import { UiValidators } from '@ui/validators';
|
||||
import { isNull } from 'lodash';
|
||||
import { isNull, merge } from 'lodash';
|
||||
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
|
||||
import {
|
||||
first,
|
||||
@@ -229,7 +229,33 @@ export abstract class AbstractCreateCustomer implements OnInit, OnDestroy {
|
||||
const customerId = this.formData?._meta?.customerDto?.id ?? this.formData?._meta?.customerInfoDto?.id;
|
||||
return this.customerService.checkLoyaltyCard({ loyaltyCardNumber: value, customerId }).pipe(
|
||||
map((response) => {
|
||||
return !response?.error && (response as any)?.result === 1 ? null : { invalid: 'Kundenkartencode ist ungültig' };
|
||||
if (response.error) {
|
||||
throw response.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* #4485 Kubi // Verhalten mit angelegte aber nicht verknüpfte Kundenkartencode in Kundensuche und Kundendaten erfassen ist nicht gleich
|
||||
* Fall1: Kundenkarte hat Daten in point4more:
|
||||
* Sobald Kundenkartencode in Feld "Kundenkartencode" reingegeben wird- werden die Daten von point4more in Formular "Kundendaten Erfassen" eingefügt und ersetzen (im Ganzen, nicht inkremental) die Daten in Felder, falls welche schon reingetippt werden.
|
||||
* Fall2: Kundenkarte hat keine Daten in point4more:
|
||||
* Sobald Kundenkartencode in Feld "Kundenkartencode" reingegeben wird- bleiben die Daten in Formular "Kundendaten Erfassen" in Felder, falls welche schon reingetippt werden.
|
||||
*/
|
||||
if (response.result && response.result.customer) {
|
||||
const customer = response.result.customer;
|
||||
const data = mapCustomerInfoDtoToCustomerCreateFormData(customer);
|
||||
|
||||
if (data.name.firstName && data.name.lastName) {
|
||||
// Fall1
|
||||
this._formData.next(data);
|
||||
} else {
|
||||
// Fall2 Hier müssen die Metadaten gesetzt werden um eine verknüfung zur kundenkarte zu ermöglichen.
|
||||
const current = this.formData;
|
||||
current._meta = data._meta;
|
||||
current.p4m = data.p4m;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}),
|
||||
catchError((error) => {
|
||||
if (error instanceof HttpErrorResponse) {
|
||||
@@ -242,31 +268,13 @@ export abstract class AbstractCreateCustomer implements OnInit, OnDestroy {
|
||||
})
|
||||
);
|
||||
}),
|
||||
tap(async (result) => {
|
||||
tap(() => {
|
||||
control.markAsTouched();
|
||||
this.cdr.markForCheck();
|
||||
|
||||
if (result === null) {
|
||||
const customerInfoDto = await this.getAnonymousCustomerForCode(control.value);
|
||||
if (customerInfoDto) {
|
||||
const data = mapCustomerInfoDtoToCustomerCreateFormData(customerInfoDto);
|
||||
this._formData.next(data);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
async getAnonymousCustomerForCode(code: string): Promise<CustomerInfoDTO | undefined> {
|
||||
try {
|
||||
const res = await this.customerService.getCustomers(code).toPromise();
|
||||
|
||||
if (res.result.length > 0 && res.result[0].id < 0) {
|
||||
return res.result[0];
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
async navigateToCustomerDetails(customer: CustomerDTO) {
|
||||
const processId = await this.processId$.pipe(first()).toPromise();
|
||||
const route = this.customerSearchNavigation.detailsRoute({ processId, customerId: customer.id, customer });
|
||||
|
||||
@@ -12,6 +12,7 @@ import { isEmpty } from 'lodash';
|
||||
import { DomainOmsService } from '@domain/oms';
|
||||
import { OrderDTO, OrderListItemDTO } from '@swagger/oms';
|
||||
import { hash } from '@utils/common';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
|
||||
@Injectable()
|
||||
export class CustomerSearchStore extends ComponentStore<CustomerSearchState> implements OnStoreInit, OnDestroy {
|
||||
@@ -163,7 +164,7 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
|
||||
|
||||
selectedOrderItem$ = this.select(S.selectSelectedOrderItem);
|
||||
|
||||
constructor(private _customerService: CrmCustomerService, private _omsService: DomainOmsService) {
|
||||
constructor(private _customerService: CrmCustomerService, private _omsService: DomainOmsService, private _modal: UiModalService) {
|
||||
super({ customerListCount: 0 });
|
||||
}
|
||||
|
||||
@@ -205,7 +206,8 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
|
||||
};
|
||||
|
||||
handleSelectCustomerError = (err: any) => {
|
||||
console.error(err);
|
||||
this._modal.error('Fehler beim Auswählen des Kundens', err);
|
||||
this.patchState({ fetchingCustomer: false });
|
||||
};
|
||||
|
||||
handleSelectCustomerComplete = () => {
|
||||
@@ -230,7 +232,8 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
|
||||
};
|
||||
|
||||
handleSelectOrderError = (err: any) => {
|
||||
console.error(err);
|
||||
this._modal.error('Fehler beim Auswählen der Bestellung', err);
|
||||
this.patchState({ fetchingOrder: false });
|
||||
};
|
||||
|
||||
handleSelectOrderComplete = () => {
|
||||
@@ -259,7 +262,8 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
|
||||
};
|
||||
|
||||
handleFetchCustomerOrdersError = (err: any) => {
|
||||
console.error(err);
|
||||
this._modal.error('Fehler beim Laden der Kundenbestellungen', err);
|
||||
this.patchState({ fetchingCustomerOrders: false });
|
||||
};
|
||||
|
||||
handleFetchCustomerOrdersComplete = () => {
|
||||
@@ -282,7 +286,8 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
|
||||
};
|
||||
|
||||
handleFetchFilterError = (err: any) => {
|
||||
console.error(err);
|
||||
this._modal.error('Fehler beim Laden der Filter', err);
|
||||
this.patchState({ fetchingFilter: false });
|
||||
};
|
||||
|
||||
handleFetchFilterComplete = () => {
|
||||
@@ -341,7 +346,8 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
|
||||
};
|
||||
|
||||
handleSearchError = (err: any) => {
|
||||
console.error(err);
|
||||
this._modal.error('Fehler beim Laden der Liste', err);
|
||||
this.patchState({ fetchingCustomerList: false });
|
||||
};
|
||||
|
||||
handleSearchComplete = () => {
|
||||
|
||||
@@ -75,7 +75,10 @@
|
||||
>Zur erneuten Prüfung 7 Tage nach Avisierung.</ui-tooltip
|
||||
>
|
||||
</ng-container>
|
||||
<div class="isa-label text-white font-bold" [class]="packageDetails.package.arrivalStatus | arrivalStatusColorClass">
|
||||
<div
|
||||
class="isa-label text-white font-bold page-package-details__arrival-status"
|
||||
[class]="packageDetails.package.arrivalStatus | arrivalStatusColorClass"
|
||||
>
|
||||
{{ packageDetails.package.arrivalStatus | arrivalStatus }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ import { RunCheckTrigger } from './trigger';
|
||||
import { OrderItemsContext } from '@domain/oms';
|
||||
import { ActionHandlerService } from './services/action-handler.service';
|
||||
import { Config } from '@core/config';
|
||||
import { debounce } from '@utils/common';
|
||||
|
||||
export type GetNameForBreadcrumbData = {
|
||||
processId: number;
|
||||
@@ -64,6 +65,11 @@ export abstract class PickupShelfBaseComponent implements OnInit {
|
||||
this._runChecks();
|
||||
}
|
||||
|
||||
// der debounce soll verhindern, dass die breadcrumb zu oft aktualisiert,
|
||||
// besonders bei asynchronen calls kommt es sonst zu fehlern
|
||||
// @debounce(500)
|
||||
// Auskommentiert, da es zu anderen Problemen führt, siehe z.B. Ticket #4538 oder #4540
|
||||
// Ursprungsproblem des Tickets #4533 konnte anders gelöst werden, somit wird debounce hier nicht mehr benötigt
|
||||
private _runChecks() {
|
||||
const processId = this._checkAndUpdateProcessId();
|
||||
const queryParams = this._checkAndUpdateQueryParams();
|
||||
@@ -120,7 +126,7 @@ export abstract class PickupShelfBaseComponent implements OnInit {
|
||||
|
||||
// Only Update QueryParams if the user is already on the details, edit or history page
|
||||
const view: string = this.activatedRoute.snapshot.data.view;
|
||||
if (['details', 'edit', 'history'].includes(view)) {
|
||||
if (['filter', 'details', 'edit', 'history'].includes(view)) {
|
||||
await this.router.navigate([], { queryParams: { ...queryParams, ...filterQueryParams }, skipLocationChange: true });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,17 +17,25 @@
|
||||
(updateDate)="updateDate($event)"
|
||||
(editClick)="navigateToEditPage($event)"
|
||||
></page-pickup-shelf-details-header>
|
||||
<page-pickup-shelf-details-item
|
||||
*ngIf="selectedItem$ | async; let item"
|
||||
class="mb-px-2"
|
||||
[orderItem]="item"
|
||||
[selected]="true"
|
||||
(historyClick)="navigateToHistoryPage($event)"
|
||||
[order]="order$ | async"
|
||||
(specialCommentChanged)="updateSpecialComment(item, $event)"
|
||||
(sharedOnInit)="fetchNotifications(item)"
|
||||
></page-pickup-shelf-details-item>
|
||||
|
||||
<ng-container *ngIf="selectedItem$ | async; let item">
|
||||
<page-pickup-shelf-details-items-group
|
||||
[orderType]="selectedItemOrderType$ | async"
|
||||
[groupedItems]="[item]"
|
||||
></page-pickup-shelf-details-items-group>
|
||||
<page-pickup-shelf-details-item
|
||||
class="mb-px-2"
|
||||
[orderItem]="item"
|
||||
[selected]="true"
|
||||
(historyClick)="navigateToHistoryPage($event)"
|
||||
[order]="order$ | async"
|
||||
(specialCommentChanged)="updateSpecialComment(item, $event)"
|
||||
(sharedOnInit)="fetchNotifications(item)"
|
||||
></page-pickup-shelf-details-item>
|
||||
</ng-container>
|
||||
|
||||
<page-pickup-shelf-details-tags class="mb-px-2" *ngIf="showTagsComponent$ | async"></page-pickup-shelf-details-tags>
|
||||
|
||||
<page-pickup-shelf-details-covers
|
||||
*ngIf="(coverOrderItems$ | async)?.length > 0"
|
||||
[coverItems]="coverOrderItems$ | async"
|
||||
|
||||
@@ -16,6 +16,7 @@ import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString } from '@swagger/
|
||||
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { RunCheckTrigger } from '../../trigger';
|
||||
import { PickUpShelfDetailsItemsGroupComponent } from '../../shared/pickup-shelf-details-items-group/pickup-shelf-details-items-group.component';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-in-details',
|
||||
@@ -32,6 +33,7 @@ import { RunCheckTrigger } from '../../trigger';
|
||||
PickUpShelfDetailsItemComponent,
|
||||
PickUpShelfDetailsTagsComponent,
|
||||
PickUpShelfDetailsCoversComponent,
|
||||
PickUpShelfDetailsItemsGroupComponent,
|
||||
PickupShelfAddToPreviousCompartmentCodeLabelPipe,
|
||||
UiSpinnerModule,
|
||||
OnInitDirective,
|
||||
@@ -74,6 +76,8 @@ export class PickupShelfInDetailsComponent extends PickupShelfDetailsBaseCompone
|
||||
|
||||
selectedItem$ = this.store.selectedOrderItem$;
|
||||
|
||||
selectedItemOrderType$ = this.selectedItem$.pipe(map((item) => item?.features?.orderType));
|
||||
|
||||
coverOrderItems$ = this.store.coverOrderItems$;
|
||||
|
||||
displayedCompartmentInfo$ = this.store.compartmentInfo$;
|
||||
|
||||
@@ -14,16 +14,24 @@
|
||||
(updateDate)="updateDate($event)"
|
||||
(editClick)="navigateToEditPage($event)"
|
||||
></page-pickup-shelf-details-header>
|
||||
<page-pickup-shelf-details-item
|
||||
class="mb-px-2"
|
||||
*ngFor="let item of orderItems$ | async; trackBy: trackByFnDBHOrderItemListItemDTO"
|
||||
[orderItem]="item"
|
||||
[selected]="true"
|
||||
(historyClick)="navigateToHistoryPage($event)"
|
||||
[order]="order$ | async"
|
||||
(specialCommentChanged)="updateSpecialComment(item, $event)"
|
||||
(sharedOnInit)="fetchNotifications(item)"
|
||||
></page-pickup-shelf-details-item>
|
||||
|
||||
<ng-container *ngFor="let group of groupedItems$ | async; trackBy: trackByFnGroupDBHOrderItemListItemDTO">
|
||||
<page-pickup-shelf-details-items-group
|
||||
[orderType]="group.type"
|
||||
[groupedItems]="group.items"
|
||||
></page-pickup-shelf-details-items-group>
|
||||
<page-pickup-shelf-details-item
|
||||
class="mb-px-2"
|
||||
*ngFor="let item of group.items; trackBy: trackByFnDBHOrderItemListItemDTO"
|
||||
[orderItem]="item"
|
||||
[selected]="true"
|
||||
(historyClick)="navigateToHistoryPage($event)"
|
||||
[order]="order$ | async"
|
||||
(specialCommentChanged)="updateSpecialComment(item, $event)"
|
||||
(sharedOnInit)="fetchNotifications(item)"
|
||||
></page-pickup-shelf-details-item>
|
||||
</ng-container>
|
||||
|
||||
<page-pickup-shelf-details-tags
|
||||
*ngIf="showTagsComponent$ | async"
|
||||
[ngModel]="selectedCompartmentInfo$ | async"
|
||||
|
||||
@@ -3,9 +3,9 @@ import { PickupShelfDetailsBaseComponent } from '../../pickup-shelf-details-base
|
||||
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
|
||||
import { PickUpShelfDetailsHeaderComponent } from '../../shared/pickup-shelf-details-header/pickup-shelf-details-header.component';
|
||||
import { PickUpShelfDetailsItemComponent } from '../../shared/pickup-shelf-details-item/pickup-shelf-details-item.component';
|
||||
import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString, OrderItemProcessingStatusValue } from '@swagger/oms';
|
||||
import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString } from '@swagger/oms';
|
||||
import { PickUpShelfOutNavigationService } from '@shared/services';
|
||||
import { BehaviorSubject, asapScheduler, combineLatest } from 'rxjs';
|
||||
import { BehaviorSubject, Observable, asapScheduler, combineLatest } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { PickUpShelfDetailsTagsComponent } from '../../shared/pickup-shelf-details-tags/pickup-shelf-details-tags.component';
|
||||
import { UiSpinnerModule } from '@ui/spinner';
|
||||
@@ -13,6 +13,7 @@ import { UiErrorModalComponent, UiModalService } from '@ui/modal';
|
||||
import { OnInitDirective } from '@shared/directives/element-lifecycle';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RunCheckTrigger } from '../../trigger';
|
||||
import { PickUpShelfDetailsItemsGroupComponent } from '../../shared/pickup-shelf-details-items-group/pickup-shelf-details-items-group.component';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-out-details',
|
||||
@@ -28,6 +29,7 @@ import { RunCheckTrigger } from '../../trigger';
|
||||
PickUpShelfDetailsHeaderComponent,
|
||||
PickUpShelfDetailsItemComponent,
|
||||
PickUpShelfDetailsTagsComponent,
|
||||
PickUpShelfDetailsItemsGroupComponent,
|
||||
UiSpinnerModule,
|
||||
OnInitDirective,
|
||||
FormsModule,
|
||||
@@ -44,7 +46,25 @@ export class PickupShelfOutDetailsComponent extends PickupShelfDetailsBaseCompon
|
||||
|
||||
order$ = this.store.order$;
|
||||
|
||||
orderItems$ = this.store.orderItems$;
|
||||
groupedItems$: Observable<Array<{ type: string; items: DBHOrderItemListItemDTO[] }>> = this.store.orderItems$.pipe(
|
||||
map((items) => {
|
||||
const groups: Array<{ type: string; items: DBHOrderItemListItemDTO[] }> = [];
|
||||
|
||||
// New Set to remove duplicates
|
||||
const types = Array.from(new Set(items.map((item) => item?.features?.orderType)));
|
||||
|
||||
for (let type of types) {
|
||||
const filteredItemsByType = items.filter((item) => item?.features?.orderType === type);
|
||||
|
||||
if (!!type && filteredItemsByType.length > 0) {
|
||||
// Add items to matching orderType group
|
||||
groups.push({ type, items: filteredItemsByType });
|
||||
}
|
||||
}
|
||||
|
||||
return groups;
|
||||
})
|
||||
);
|
||||
|
||||
fetching$ = this.store.fetchingOrder$;
|
||||
fetchingItems$ = this.store.fetchingOrderItems$;
|
||||
@@ -66,6 +86,8 @@ export class PickupShelfOutDetailsComponent extends PickupShelfDetailsBaseCompon
|
||||
|
||||
mainActions$ = this.store.mainActions$;
|
||||
|
||||
trackByFnGroupDBHOrderItemListItemDTO = (index: number, group: { type: string; items: DBHOrderItemListItemDTO[] }) => group.type;
|
||||
|
||||
trackByFnDBHOrderItemListItemDTO = (index: number, item: DBHOrderItemListItemDTO) => item.orderItemSubsetId;
|
||||
|
||||
get processId() {
|
||||
|
||||
@@ -145,96 +145,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row items-center relative bg-[#F5F7FA] p-4 rounded-t">
|
||||
<div *ngIf="showFeature" class="flex flex-row items-center mr-3">
|
||||
<ng-container [ngSwitch]="order.features.orderType">
|
||||
<ng-container *ngSwitchCase="'Versand'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-truck"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Versand</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'DIG-Versand'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-truck"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Versand</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'B2B-Versand'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-b2b-truck"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">B2B-Versand</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'Abholung'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-box-out"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1 mr-3">Abholung</p>
|
||||
{{ orderItem.targetBranch }}
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'Rücklage'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-shopping-bag"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Rücklage</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'Download'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-download"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Download</p>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-details-header__additional-addresses" *ngIf="showAddresses">
|
||||
<button (click)="openAddresses = !openAddresses" class="text-[#0556B4]">
|
||||
Lieferadresse / Rechnungsadresse {{ openAddresses ? 'ausblenden' : 'anzeigen' }}
|
||||
</button>
|
||||
|
||||
<div class="page-pickup-shelf-details-header__addresses-popover" *ngIf="openAddresses">
|
||||
<button (click)="openAddresses = !openAddresses" class="close">
|
||||
<shared-icon icon="close" [size]="24"></shared-icon>
|
||||
</button>
|
||||
|
||||
<div class="page-pickup-shelf-details-header__addresses-popover-data">
|
||||
<div *ngIf="order.shipping" class="page-pickup-shelf-details-header__addresses-popover-delivery">
|
||||
<p>Lieferadresse</p>
|
||||
<div class="page-pickup-shelf-details-header__addresses-popover-delivery-data">
|
||||
<ng-container *ngIf="order.shipping?.data?.organisation">
|
||||
<p>{{ order.shipping?.data?.organisation?.name }}</p>
|
||||
<p>{{ order.shipping?.data?.organisation?.department }}</p>
|
||||
</ng-container>
|
||||
<p>{{ order.shipping?.data?.firstName }} {{ order.shipping?.data?.lastName }}</p>
|
||||
<p>{{ order.shipping?.data?.address?.info }}</p>
|
||||
<p>{{ order.shipping?.data?.address?.street }} {{ order.shipping?.data?.address?.streetNumber }}</p>
|
||||
<p>{{ order.shipping?.data?.address?.zipCode }} {{ order.shipping?.data?.address?.city }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="order.billing" class="page-pickup-shelf-details-header__addresses-popover-billing">
|
||||
<p>Rechnungsadresse</p>
|
||||
<div class="page-pickup-shelf-details-header__addresses-popover-billing-data">
|
||||
<ng-container *ngIf="order.billing?.data?.organisation">
|
||||
<p>{{ order.billing?.data?.organisation?.name }}</p>
|
||||
<p>{{ order.billing?.data?.organisation?.department }}</p>
|
||||
</ng-container>
|
||||
<p>{{ order.billing?.data?.firstName }} {{ order.billing?.data?.lastName }}</p>
|
||||
<p>{{ order.billing?.data?.address?.info }}</p>
|
||||
<p>{{ order.billing?.data?.address?.street }} {{ order.billing?.data?.address?.streetNumber }}</p>
|
||||
<p>{{ order.billing?.data?.address?.zipCode }} {{ order.billing?.data?.address?.city }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-details-header__select grow" *ngIf="showMultiselect$ | async">
|
||||
<button class="cta-select-all" (click)="selectAll()">Alle auswählen</button>
|
||||
{{ selectedOrderItemCount$ | async }} von {{ orderItemCount$ | async }} Titeln
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #featureLoading>
|
||||
|
||||
@@ -81,51 +81,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-header__select {
|
||||
@apply flex flex-col items-end;
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-header__additional-addresses {
|
||||
.page-pickup-shelf-details-header__addresses-popover {
|
||||
@apply absolute inset-x-0 top-16 bottom-0 z-popover;
|
||||
|
||||
.close {
|
||||
@apply bg-white absolute right-0 p-6;
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-header__addresses-popover-data {
|
||||
@apply flex flex-col bg-white p-6 z-popover min-h-[200px];
|
||||
box-shadow: 0px 6px 24px rgba(206, 212, 219, 0.8);
|
||||
|
||||
.page-pickup-shelf-details-header__addresses-popover-delivery {
|
||||
@apply grid mb-6;
|
||||
grid-template-columns: 9.5625rem auto;
|
||||
|
||||
.page-pickup-shelf-details-header__addresses-popover-delivery-data {
|
||||
p {
|
||||
@apply font-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-header__addresses-popover-billing {
|
||||
@apply grid;
|
||||
grid-template-columns: 9.5625rem auto;
|
||||
|
||||
.page-pickup-shelf-details-header__addresses-popover-billing-data {
|
||||
p {
|
||||
@apply font-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cta-select-all {
|
||||
@apply text-brand bg-transparent text-p2 font-bold outline-none border-none;
|
||||
}
|
||||
|
||||
.fetch-wrapper {
|
||||
@apply grid grid-flow-col gap-4;
|
||||
}
|
||||
|
||||
@@ -92,10 +92,6 @@ export class PickUpShelfDetailsHeaderComponent {
|
||||
minDateDatepicker = this.dateAdapter.addCalendarDays(this.dateAdapter.today(), -1);
|
||||
today = this.dateAdapter.today();
|
||||
|
||||
selectedOrderItemCount$ = this._store.selectedOrderItemIds$.pipe(map((ids) => ids?.length ?? 0));
|
||||
|
||||
orderItemCount$ = this._store.orderItems$.pipe(map((items) => items?.length ?? 0));
|
||||
|
||||
orderItem$ = this._store.orderItems$.pipe(map((orderItems) => orderItems?.find((_) => true)));
|
||||
|
||||
changeDateLoader$ = new BehaviorSubject<boolean>(false);
|
||||
@@ -115,14 +111,6 @@ export class PickUpShelfDetailsHeaderComponent {
|
||||
|
||||
statusActions$ = this.orderItem$.pipe(map((orderItem) => orderItem?.actions?.filter((action) => action.enabled === false)));
|
||||
|
||||
get isItemSelectable() {
|
||||
return this._store.orderItems?.some((item) => !!item?.actions && item?.actions?.length > 0);
|
||||
}
|
||||
|
||||
showMultiselect$ = combineLatest([this._store.orderItems$, this._store.fetchPartial$]).pipe(
|
||||
map(([orderItems, fetchPartial]) => this.isItemSelectable && fetchPartial && orderItems?.length > 1)
|
||||
);
|
||||
|
||||
crudaUpdate$ = this.orderItem$.pipe(map((orederItem) => !!(orederItem?.cruda & 4)));
|
||||
|
||||
editButtonDisabled$ = combineLatest([this.changeStatusLoader$, this.crudaUpdate$]).pipe(
|
||||
@@ -133,20 +121,6 @@ export class PickUpShelfDetailsHeaderComponent {
|
||||
map(([statusActions, crudaUpdate]) => statusActions?.length > 0 && crudaUpdate)
|
||||
);
|
||||
|
||||
openAddresses: boolean = false;
|
||||
|
||||
get digOrderNumber(): string {
|
||||
return this.order?.linkedRecords?.find((_) => true)?.number;
|
||||
}
|
||||
|
||||
get showAddresses(): boolean {
|
||||
return (this.order?.orderType === 2 || this.order?.orderType === 4) && (!!this.order?.shipping || !!this.order?.billing);
|
||||
}
|
||||
|
||||
get showFeature(): boolean {
|
||||
return !!this.order?.features && !!this.order?.features?.orderType;
|
||||
}
|
||||
|
||||
constructor(private dateAdapter: DateAdapter, private cdr: ChangeDetectorRef) {}
|
||||
|
||||
async handleActionClick(action?: KeyValueDTOOfStringAndString) {
|
||||
@@ -156,10 +130,6 @@ export class PickUpShelfDetailsHeaderComponent {
|
||||
this.cdr.markForCheck();
|
||||
}
|
||||
|
||||
selectAll() {
|
||||
this._store.selectAllOrderItemIds();
|
||||
}
|
||||
|
||||
updatePickupDeadline(date: Date) {
|
||||
this.updateDate.emit({ date, type: 'pickup' });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
<div class="flex flex-row items-center relative bg-[#F5F7FA] p-4 rounded-t mb-[0.125rem]">
|
||||
<div *ngIf="showFeature" class="flex flex-row items-center mr-3">
|
||||
<ng-container [ngSwitch]="orderType">
|
||||
<ng-container *ngSwitchCase="'Versand'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-truck"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Versand</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'DIG-Versand'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-truck"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Versand</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'B2B-Versand'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-b2b-truck"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">B2B-Versand</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'Abholung'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-box-out"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1 mr-3">Abholung</p>
|
||||
{{ targetBranches }}
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'Rücklage'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-shopping-bag"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Rücklage</p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'Download'">
|
||||
<div class="flex items-center justify-center bg-[#D8DFE5] w-[2.25rem] h-[2.25rem] rounded rounded-br-none mr-2">
|
||||
<shared-icon [size]="24" icon="isa-download"></shared-icon>
|
||||
</div>
|
||||
<p class="font-bold text-p1">Download</p>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-details-items-group__additional-addresses" *ngIf="showAddresses">
|
||||
<button (click)="openAddresses = !openAddresses" class="text-[#0556B4]">
|
||||
Lieferadresse / Rechnungsadresse {{ openAddresses ? 'ausblenden' : 'anzeigen' }}
|
||||
</button>
|
||||
|
||||
<div class="page-pickup-shelf-details-items-group__addresses-popover" *ngIf="openAddresses">
|
||||
<button (click)="openAddresses = !openAddresses" class="close">
|
||||
<shared-icon icon="close" [size]="24"></shared-icon>
|
||||
</button>
|
||||
|
||||
<div class="page-pickup-shelf-details-items-group__addresses-popover-data">
|
||||
<div *ngIf="order.shipping" class="page-pickup-shelf-details-items-group__addresses-popover-delivery">
|
||||
<p>Lieferadresse</p>
|
||||
<div class="page-pickup-shelf-details-items-group__addresses-popover-delivery-data">
|
||||
<ng-container *ngIf="order.shipping?.data?.organisation">
|
||||
<p>{{ order.shipping?.data?.organisation?.name }}</p>
|
||||
<p>{{ order.shipping?.data?.organisation?.department }}</p>
|
||||
</ng-container>
|
||||
<p>{{ order.shipping?.data?.firstName }} {{ order.shipping?.data?.lastName }}</p>
|
||||
<p>{{ order.shipping?.data?.address?.info }}</p>
|
||||
<p>{{ order.shipping?.data?.address?.street }} {{ order.shipping?.data?.address?.streetNumber }}</p>
|
||||
<p>{{ order.shipping?.data?.address?.zipCode }} {{ order.shipping?.data?.address?.city }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="order.billing" class="page-pickup-shelf-details-items-group__addresses-popover-billing">
|
||||
<p>Rechnungsadresse</p>
|
||||
<div class="page-pickup-shelf-details-items-group__addresses-popover-billing-data">
|
||||
<ng-container *ngIf="order.billing?.data?.organisation">
|
||||
<p>{{ order.billing?.data?.organisation?.name }}</p>
|
||||
<p>{{ order.billing?.data?.organisation?.department }}</p>
|
||||
</ng-container>
|
||||
<p>{{ order.billing?.data?.firstName }} {{ order.billing?.data?.lastName }}</p>
|
||||
<p>{{ order.billing?.data?.address?.info }}</p>
|
||||
<p>{{ order.billing?.data?.address?.street }} {{ order.billing?.data?.address?.streetNumber }}</p>
|
||||
<p>{{ order.billing?.data?.address?.zipCode }} {{ order.billing?.data?.address?.city }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-pickup-shelf-details-items-group__select grow" *ngIf="showMultiselect$ | async">
|
||||
<button class="cta-select-all" (click)="selectAll()">Alle auswählen</button>
|
||||
{{ selectedOrderItemCount$ | async }} von {{ groupedItems.length }} Titeln
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,48 @@
|
||||
:host {
|
||||
@apply grid grid-flow-row;
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-items-group__select {
|
||||
@apply flex flex-col items-end;
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-items-group__additional-addresses {
|
||||
.page-pickup-shelf-details-items-group__addresses-popover {
|
||||
@apply absolute inset-x-0 top-16 bottom-0 z-popover;
|
||||
|
||||
.close {
|
||||
@apply bg-white absolute right-0 p-6;
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-items-group__addresses-popover-data {
|
||||
@apply flex flex-col bg-white p-6 z-popover min-h-[200px];
|
||||
box-shadow: 0px 6px 24px rgba(206, 212, 219, 0.8);
|
||||
|
||||
.page-pickup-shelf-details-items-group__addresses-popover-delivery {
|
||||
@apply grid mb-6;
|
||||
grid-template-columns: 9.5625rem auto;
|
||||
|
||||
.page-pickup-shelf-details-items-group__addresses-popover-delivery-data {
|
||||
p {
|
||||
@apply font-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-pickup-shelf-details-items-group__addresses-popover-billing {
|
||||
@apply grid;
|
||||
grid-template-columns: 9.5625rem auto;
|
||||
|
||||
.page-pickup-shelf-details-items-group__addresses-popover-billing-data {
|
||||
p {
|
||||
@apply font-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cta-select-all {
|
||||
@apply text-brand bg-transparent text-p2 font-bold outline-none border-none;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, inject } from '@angular/core';
|
||||
import { PickupShelfDetailsStore } from '../../store';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { DBHOrderItemListItemDTO, OrderDTO } from '@swagger/oms';
|
||||
import { AsyncPipe, NgFor, NgIf, NgSwitch, NgSwitchCase } from '@angular/common';
|
||||
import { IconModule } from '@shared/components/icon';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-details-items-group',
|
||||
templateUrl: 'pickup-shelf-details-items-group.component.html',
|
||||
styleUrls: ['pickup-shelf-details-items-group.component.scss'],
|
||||
standalone: true,
|
||||
host: { class: 'page-pickup-shelf-details-items-group' },
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [NgIf, NgFor, NgSwitch, NgSwitchCase, IconModule, AsyncPipe],
|
||||
})
|
||||
export class PickUpShelfDetailsItemsGroupComponent implements OnInit {
|
||||
private _store = inject(PickupShelfDetailsStore);
|
||||
|
||||
get order(): OrderDTO {
|
||||
return this._store.order;
|
||||
}
|
||||
|
||||
@Input() orderType: string;
|
||||
|
||||
@Input() groupedItems: DBHOrderItemListItemDTO[];
|
||||
|
||||
get firstGroupedItem() {
|
||||
return this.groupedItems?.find((_) => true);
|
||||
}
|
||||
|
||||
openAddresses: boolean = false;
|
||||
|
||||
get showAddresses(): boolean {
|
||||
return (this.order?.orderType === 2 || this.order?.orderType === 4) && (!!this.order?.shipping || !!this.order?.billing);
|
||||
}
|
||||
|
||||
get showFeature(): boolean {
|
||||
return !!this.firstGroupedItem?.features && !!this.firstGroupedItem?.features?.orderType;
|
||||
}
|
||||
|
||||
get targetBranches(): string {
|
||||
return Array.from(new Set(this.groupedItems?.map((item) => item?.targetBranch))).join('; ');
|
||||
}
|
||||
|
||||
get isItemSelectable() {
|
||||
return this.groupedItems?.some((item) => !!item?.actions && item?.actions?.length > 0);
|
||||
}
|
||||
|
||||
showMultiselect$ = this._store.fetchPartial$.pipe(
|
||||
map((fetchPartial) => this.isItemSelectable && fetchPartial && this.groupedItems?.length > 1)
|
||||
);
|
||||
|
||||
selectedOrderItemCount$ = this._store.selectedOrderItemIds$.pipe(
|
||||
map((ids) => this.groupedItems?.filter((groupedItem) => ids?.includes(groupedItem?.orderItemSubsetId))?.length ?? 0)
|
||||
);
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
selectAll() {
|
||||
this._store.selectAllOrderItemIds();
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,13 @@ export class PickupShelfStore extends ComponentStore<PickupShelfState> implement
|
||||
}
|
||||
|
||||
setQueryParams(queryParams: Record<string, string> | undefined) {
|
||||
this.patchState({ queryParams });
|
||||
// #4533 Wenn ein Abholschein gescannt wird, soll ORD: nicht in der Suchbox stehen und somit auch nicht in der Breadcrumb enthalten sein
|
||||
const isScannedPickUpCode = queryParams?.main_qs?.includes('ORD:');
|
||||
if (isScannedPickUpCode) {
|
||||
this.patchState({ queryParams: { ...queryParams, main_qs: queryParams?.main_qs?.replace('ORD:', '') } });
|
||||
} else {
|
||||
this.patchState({ queryParams });
|
||||
}
|
||||
}
|
||||
|
||||
cancelListRequests() {
|
||||
|
||||
@@ -152,10 +152,7 @@ export class SharedGoodsInOutOrderEditComponent implements OnChanges, OnDestroy
|
||||
name: fb.control(item.product?.name),
|
||||
ean: fb.control(item.product?.ean, [Validators.required]),
|
||||
quantity: fb.control({ value: item.quantity + ' x', disabled: true }),
|
||||
price: fb.control(item.price ? String(item.price).replace('.', ',') : '', [
|
||||
Validators.required,
|
||||
Validators.pattern(/^\d+([\,]\d{1,2})?$/),
|
||||
]),
|
||||
price: fb.control(this.formatPrice(item?.price), [Validators.required, Validators.pattern(/^\d+([\,]\d{1,2})?$/)]),
|
||||
currency: fb.control(item.currency),
|
||||
targetBranch: fb.control({ value: item.targetBranch, disabled: true }),
|
||||
supplier: fb.control({ value: item.supplier, disabled: true }),
|
||||
@@ -208,6 +205,15 @@ export class SharedGoodsInOutOrderEditComponent implements OnChanges, OnDestroy
|
||||
return this.omsService.getOrderSource(+orderId).toPromise();
|
||||
}
|
||||
|
||||
formatPrice(price: number) {
|
||||
if (!price) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const priceWithTwoDecimalPlaces = price.toFixed(2);
|
||||
return String(priceWithTwoDecimalPlaces).replace('.', ',');
|
||||
}
|
||||
|
||||
changeEstimatedDeliveryDate(date: Date, item: OrderItemListItemDTO) {
|
||||
if (!date) {
|
||||
return;
|
||||
|
||||
@@ -98,7 +98,8 @@
|
||||
class="side-menu-group-item"
|
||||
(click)="closeSideMenu(); resetBranch(); focusSearchBox()"
|
||||
[routerLink]="customerOrdersRoutePath$ | async"
|
||||
routerLinkActive="active"
|
||||
sharedRegexRouterLinkActive="active"
|
||||
sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/order"
|
||||
(isActiveChange)="focusSearchBox()"
|
||||
>
|
||||
<span class="side-menu-group-item-icon">
|
||||
|
||||
@@ -7,7 +7,6 @@ export { DialogOfString } from './models/dialog-of-string';
|
||||
export { DialogSettings } from './models/dialog-settings';
|
||||
export { DialogContentType } from './models/dialog-content-type';
|
||||
export { KeyValueDTOOfStringAndString } from './models/key-value-dtoof-string-and-string';
|
||||
export { IPublicUserInfo } from './models/ipublic-user-info';
|
||||
export { ProblemDetails } from './models/problem-details';
|
||||
export { ResponseArgsOfIEnumerableOfCountryDTO } from './models/response-args-of-ienumerable-of-country-dto';
|
||||
export { CountryDTO } from './models/country-dto';
|
||||
@@ -15,6 +14,7 @@ export { EntityDTOBaseOfCountryDTOAndICountry } from './models/entity-dtobase-of
|
||||
export { EntityDTOBase } from './models/entity-dtobase';
|
||||
export { EntityDTO } from './models/entity-dto';
|
||||
export { EntityStatus } from './models/entity-status';
|
||||
export { CRUDA } from './models/cruda';
|
||||
export { ResponseArgsOfInputDTO } from './models/response-args-of-input-dto';
|
||||
export { InputDTO } from './models/input-dto';
|
||||
export { InputType } from './models/input-type';
|
||||
@@ -92,5 +92,8 @@ export { DiffDTO } from './models/diff-dto';
|
||||
export { ResponseArgsOfIEnumerableOfEntityKeyValueDTOOfStringAndString } from './models/response-args-of-ienumerable-of-entity-key-value-dtoof-string-and-string';
|
||||
export { EntityKeyValueDTOOfStringAndString } from './models/entity-key-value-dtoof-string-and-string';
|
||||
export { ResponseArgsOfIEnumerableOfKeyValueDTOOfStringAndString } from './models/response-args-of-ienumerable-of-key-value-dtoof-string-and-string';
|
||||
export { ResponseArgsOfCheckLoyaltyCardResult } from './models/response-args-of-check-loyalty-card-result';
|
||||
export { CheckLoyaltyCardResult } from './models/check-loyalty-card-result';
|
||||
export { LoyaltyCardStatus } from './models/loyalty-card-status';
|
||||
export { ResponseArgsOfPayerDTO } from './models/response-args-of-payer-dto';
|
||||
export { ResponseArgsOfShippingAddressDTO } from './models/response-args-of-shipping-address-dto';
|
||||
|
||||
15
apps/swagger/crm/src/lib/models/check-loyalty-card-result.ts
Normal file
15
apps/swagger/crm/src/lib/models/check-loyalty-card-result.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/* tslint:disable */
|
||||
import { CustomerInfoDTO } from './customer-info-dto';
|
||||
import { LoyaltyCardStatus } from './loyalty-card-status';
|
||||
export interface CheckLoyaltyCardResult {
|
||||
|
||||
/**
|
||||
* Customer
|
||||
*/
|
||||
customer?: CustomerInfoDTO;
|
||||
|
||||
/**
|
||||
* Status
|
||||
*/
|
||||
status: LoyaltyCardStatus;
|
||||
}
|
||||
2
apps/swagger/crm/src/lib/models/cruda.ts
Normal file
2
apps/swagger/crm/src/lib/models/cruda.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
/* tslint:disable */
|
||||
export type CRUDA = 0 | 1 | 2 | 4 | 8 | 16;
|
||||
@@ -1,11 +1,14 @@
|
||||
/* tslint:disable */
|
||||
import { TouchedBase } from './touched-base';
|
||||
import { CRUDA } from './cruda';
|
||||
import { EntityStatus } from './entity-status';
|
||||
export interface EntityDTO extends TouchedBase{
|
||||
changed?: string;
|
||||
created?: string;
|
||||
cruda?: CRUDA;
|
||||
id?: number;
|
||||
pId?: string;
|
||||
status?: EntityStatus;
|
||||
uId?: string;
|
||||
version?: number;
|
||||
}
|
||||
|
||||
@@ -8,4 +8,5 @@ export interface EntityDTOReferenceContainer extends TouchedBase{
|
||||
id?: number;
|
||||
pId?: string;
|
||||
selected?: boolean;
|
||||
uId?: string;
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/* tslint:disable */
|
||||
export interface IPublicUserInfo {
|
||||
alias?: string;
|
||||
displayName?: string;
|
||||
isAuthenticated: boolean;
|
||||
username?: string;
|
||||
}
|
||||
6
apps/swagger/crm/src/lib/models/loyalty-card-status.ts
Normal file
6
apps/swagger/crm/src/lib/models/loyalty-card-status.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/* tslint:disable */
|
||||
|
||||
/**
|
||||
* Kundenkartenstatus
|
||||
*/
|
||||
export type LoyaltyCardStatus = 0 | 1 | 2 | 4 | 8;
|
||||
@@ -0,0 +1,6 @@
|
||||
/* tslint:disable */
|
||||
import { ResponseArgs } from './response-args';
|
||||
import { CheckLoyaltyCardResult } from './check-loyalty-card-result';
|
||||
export interface ResponseArgsOfCheckLoyaltyCardResult extends ResponseArgs{
|
||||
result?: CheckLoyaltyCardResult;
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
/* tslint:disable */
|
||||
import { DialogOfString } from './dialog-of-string';
|
||||
import { IPublicUserInfo } from './ipublic-user-info';
|
||||
export interface ResponseArgs {
|
||||
dialog?: DialogOfString;
|
||||
error: boolean;
|
||||
invalidProperties?: {[key: string]: string};
|
||||
message?: string;
|
||||
requestId?: number;
|
||||
userInfo?: IPublicUserInfo;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { map as __map, filter as __filter } from 'rxjs/operators';
|
||||
|
||||
import { ResponseArgsOfIEnumerableOfEntityKeyValueDTOOfStringAndString } from '../models/response-args-of-ienumerable-of-entity-key-value-dtoof-string-and-string';
|
||||
import { ResponseArgsOfIEnumerableOfKeyValueDTOOfStringAndString } from '../models/response-args-of-ienumerable-of-key-value-dtoof-string-and-string';
|
||||
import { ResponseArgsOfQuerySettingsDTO } from '../models/response-args-of-query-settings-dto';
|
||||
import { ResponseArgsOfCheckLoyaltyCardResult } from '../models/response-args-of-check-loyalty-card-result';
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
@@ -121,7 +121,7 @@ class LoyaltyCardService extends __BaseService {
|
||||
*
|
||||
* - `customerId`: PK Kunde (optional)
|
||||
*/
|
||||
LoyaltyCardCheckLoyaltyCardResponse(params: LoyaltyCardService.LoyaltyCardCheckLoyaltyCardParams): __Observable<__StrictHttpResponse<ResponseArgsOfQuerySettingsDTO>> {
|
||||
LoyaltyCardCheckLoyaltyCardResponse(params: LoyaltyCardService.LoyaltyCardCheckLoyaltyCardParams): __Observable<__StrictHttpResponse<ResponseArgsOfCheckLoyaltyCardResult>> {
|
||||
let __params = this.newParams();
|
||||
let __headers = new HttpHeaders();
|
||||
let __body: any = null;
|
||||
@@ -141,7 +141,7 @@ class LoyaltyCardService extends __BaseService {
|
||||
return this.http.request<any>(req).pipe(
|
||||
__filter(_r => _r instanceof HttpResponse),
|
||||
__map((_r) => {
|
||||
return _r as __StrictHttpResponse<ResponseArgsOfQuerySettingsDTO>;
|
||||
return _r as __StrictHttpResponse<ResponseArgsOfCheckLoyaltyCardResult>;
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -155,9 +155,9 @@ class LoyaltyCardService extends __BaseService {
|
||||
*
|
||||
* - `customerId`: PK Kunde (optional)
|
||||
*/
|
||||
LoyaltyCardCheckLoyaltyCard(params: LoyaltyCardService.LoyaltyCardCheckLoyaltyCardParams): __Observable<ResponseArgsOfQuerySettingsDTO> {
|
||||
LoyaltyCardCheckLoyaltyCard(params: LoyaltyCardService.LoyaltyCardCheckLoyaltyCardParams): __Observable<ResponseArgsOfCheckLoyaltyCardResult> {
|
||||
return this.LoyaltyCardCheckLoyaltyCardResponse(params).pipe(
|
||||
__map(_r => _r.body as ResponseArgsOfQuerySettingsDTO)
|
||||
__map(_r => _r.body as ResponseArgsOfCheckLoyaltyCardResult)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
9
apps/utils/common/src/lib/debounce.decorator.ts
Normal file
9
apps/utils/common/src/lib/debounce.decorator.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { DebounceSettings, debounce as lodashDebounce } from 'lodash';
|
||||
|
||||
export function debounce(wait: number, options?: DebounceSettings): MethodDecorator {
|
||||
return (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>): TypedPropertyDescriptor<any> => {
|
||||
const currentMethod = descriptor.value;
|
||||
descriptor.value = lodashDebounce(currentMethod, wait, options);
|
||||
return descriptor;
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './contains-element';
|
||||
export * from './debounce.decorator';
|
||||
export * from './geo-distance';
|
||||
export * from './hash';
|
||||
export * from './is-array';
|
||||
|
||||
@@ -114,6 +114,9 @@
|
||||
"@shared/directives/*": [
|
||||
"apps/shared/directives/*/src/public-api.ts"
|
||||
],
|
||||
"@shared/services/*": [
|
||||
"apps/shared/services/*/src/public-api.ts"
|
||||
],
|
||||
"@shared/pipes/*": [
|
||||
"apps/shared/pipes/*/src/public-api.ts"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user