Compare commits

...

19 Commits

Author SHA1 Message Date
Nino
78abd0046e #4552 Added whitespace 2024-01-05 10:06:32 +01:00
Anastasiia Chetverykova
7809e7a2b5 Merged PR 1717: #4552 - Packstückprüfung Anzahl Exemplare
#4552 - Packstückprüfung Anzahl Exemplare
2024-01-04 13:35:57 +00:00
Nino Righi
9a8c74b148 Merged PR 1716: #4534 Goods In Out Order Edit Always Show Price with Two Decimal Places
#4534 Goods In Out Order Edit Always Show Price with Two Decimal Places
2024-01-04 10:36:37 +00:00
Nino Righi
ad62e67771 Merged PR 1715: #4525 Improved Scroll Position Handling in Goods In List and Remission Previe...
#4525 Improved Scroll Position Handling in Goods In List and Remission Preview Page
2024-01-04 09:23:28 +00:00
Nino Righi
6feb8079b7 Merged PR 1714: #4550 Fix Multiple Processes Bug
#4550 Fix Multiple Processes Bug
2024-01-04 08:23:31 +00:00
Nino
7f8f48f393 Updated tsconfig 2024-01-03 11:54:03 +01:00
Nino
0fe0c5242d Merge branch 'release/3.0' into develop 2024-01-03 11:52:25 +01:00
Nino
d208bdaf97 Added Package Inspection Class Name in Details Page for Page Objects Targetting 2024-01-02 15:08:19 +01:00
Nino Righi
dc80df4ad4 Merged PR 1712: #4524 Page Article Search Improved Order by Filter Handling
#4524 Page Article Search Improved Order by Filter Handling
2023-12-29 16:12:53 +00:00
Nino Righi
0973b01bf0 Merged PR 1704: #4539 Fix Skip Location Change Filter
#4539 Fix Skip Location Change Filter
2023-12-27 14:39:15 +00:00
Nino Righi
2ff033ea55 Merged PR 1701: #4539 Hotfix AHF Open Filter Page does not trigger search request
#4539 Hotfix AHF Open Filter Page does not trigger search request
2023-12-21 17:23:08 +00:00
Nino Righi
cbaac8ed9a Merged PR 1700: #4537 Relocated Component Store provision
#4537 Relocated Component Store provision
2023-12-21 17:19:35 +00:00
Lorenz Hilpert
803a8e316c Skip UnitTest for some libs 2023-12-19 17:33:19 +01:00
Nino Righi
83cab7796e Merged PR 1697: #4530 Notification Batch Messages for each type
#4530 Notification Batch Messages for each type

(cherry picked from commit 5073693fc2)
2023-12-19 17:14:37 +01:00
Nino Righi
c70dd30830 Merged PR 1695: #4523 AHF, WA Added other notification types to Email Notification Badge
#4523 AHF, WA Added other notification types to Email Notification Badge

(cherry picked from commit f3cb6236a5)
2023-12-19 17:14:03 +01:00
Lorenz Hilpert
b28bb165d4 Merged PR 1696: #4532 Mitarbeiter klickt auf Einbuchen und erreicht den Tätigkeitskalender
#4532 Mitarbeiter klickt auf Einbuchen und erreicht den Tätigkeitskalender
2023-12-19 13:35:58 +00:00
Nino Righi
32d8d81f53 Merged PR 1694: #4526 Hotfix Pickup Shelf Edit show Erneut Senden CTA
#4526 Hotfix Pickup Shelf Edit show Erneut Senden CTA
2023-12-15 10:12:51 +00:00
Nino
0361aa63ff Merge Develop into Release/3.0, corrected itemSize in page catalog list 2023-12-12 16:52:03 +01:00
Nino
2f95c23910 Merge branch 'develop' into release/3.0 2023-12-12 16:35:35 +01:00
19 changed files with 175 additions and 154 deletions

View File

@@ -6,12 +6,10 @@ import { ArticleSearchComponent } from './article-search.component';
import { SearchResultsModule } from './search-results/search-results.module';
import { SearchMainModule } from './search-main/search-main.module';
import { SearchFilterModule } from './search-filter/search-filter.module';
import { ArticleSearchService } from './article-search.store';
@NgModule({
imports: [CommonModule, RouterModule, UiIconModule, SearchResultsModule, SearchMainModule, SearchFilterModule],
exports: [ArticleSearchComponent],
declarations: [ArticleSearchComponent],
providers: [ArticleSearchService],
})
export class ArticleSearchModule {}

View File

@@ -40,14 +40,15 @@
<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>
<ng-container *ngIf="primaryOutletActive$ | async; else sideOutlet">
<cdk-virtual-scroll-viewport class="product-list" [itemSize]="106 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)">
<cdk-virtual-scroll-viewport class="product-list" [itemSize]="103 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)">
<a
*cdkVirtualFor="let item of results$ | async; let i = index; trackBy: trackByItemId"
[routerLink]="getDetailsPath(item.id)"
@@ -81,7 +82,7 @@
</ng-container>
<ng-template #sideOutlet>
<cdk-virtual-scroll-viewport class="product-list" [itemSize]="222 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)">
<cdk-virtual-scroll-viewport class="product-list" [itemSize]="191 * (scale$ | async)" (scrolledIndexChange)="scrolledIndexChange($event)">
<a
*cdkVirtualFor="let item of results$ | async; let i = index; trackBy: trackByItemId"
[routerLink]="getDetailsPath(item.id)"

View File

@@ -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

View File

@@ -11,12 +11,14 @@ import { combineLatest, fromEvent, Observable, Subject } from 'rxjs';
import { first, map, switchMap, takeUntil, withLatestFrom } from 'rxjs/operators';
import { ActionsSubject } from '@ngrx/store';
import { DomainAvailabilityService } from '@domain/availability';
import { provideComponentStore } from '@ngrx/component-store';
import { ArticleSearchService } from './article-search/article-search.store';
@Component({
selector: 'page-catalog',
templateUrl: 'page-catalog.component.html',
styleUrls: ['page-catalog.component.scss'],
providers: [],
providers: [provideComponentStore(ArticleSearchService)],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PageCatalogComponent implements OnInit, AfterViewInit, OnDestroy {

View File

@@ -1,58 +0,0 @@
import { Directive, HostListener, Input, Output, EventEmitter, OnInit } from '@angular/core';
import { BranchDTO } from '@swagger/checkout';
import { PurchasingOptionsModalStore } from '../../modals/purchasing-options-modal/purchasing-options-modal.store';
/* tslint:disable: directive-selector */
@Directive({ selector: '[keyNavigation]' })
export class KeyNavigationDirective implements OnInit {
@Input() element: any;
@Input('keyNavigation') data: BranchDTO[];
@Output() closeDropdown = new EventEmitter<void>();
@Output() preselectBranch = new EventEmitter<BranchDTO>();
selectedData: BranchDTO;
position = 0;
posMarker = 0;
@HostListener('window:keyup', ['$event'])
keyEvent(event: KeyboardEvent) {
if (event.key === 'ArrowUp') {
if (this.position > 0) {
this.position--;
}
if (this.position <= this.posMarker - 4) {
this.element.scrollTop -= 44;
}
this.selectedData = this.data[this.position];
this.preselectBranch.emit(this.selectedData);
}
if (event.key === 'ArrowDown') {
if (this.position < this.data.length - 1) {
this.position++;
}
if (this.position >= 4) {
this.posMarker = this.position;
this.element.scrollTop += 44;
}
this.selectedData = this.data[this.position];
this.preselectBranch.emit(this.selectedData);
}
if (event.key === 'Enter') {
this.purchasingOptionsModalStore.setBranch(this.selectedData);
this.position = 0;
this.closeDropdown.emit();
}
}
constructor(private purchasingOptionsModalStore: PurchasingOptionsModalStore) {}
ngOnInit() {
this.selectedData = this.data[this.position];
this.preselectBranch.emit(this.selectedData);
}
}

View File

@@ -1,12 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { KeyNavigationDirective } from './key-navigation.directive';
@NgModule({
imports: [CommonModule],
exports: [KeyNavigationDirective],
declarations: [KeyNavigationDirective],
providers: [],
})
export class KeyNavigationModule {}

View File

@@ -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,
@@ -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());
}
@@ -416,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;
@@ -435,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 });
}

View File

@@ -3,6 +3,7 @@ import { ActivatedRoute } from '@angular/router';
import { ApplicationService } from '@core/application';
import { AuthService } from '@core/auth';
import { EnvironmentService } from '@core/environment';
import { provideComponentStore } from '@ngrx/component-store';
import { BranchSelectorComponent } from '@shared/components/branch-selector';
import { BreadcrumbComponent } from '@shared/components/breadcrumb';
import { BranchDTO } from '@swagger/checkout';
@@ -16,7 +17,7 @@ import { CustomerOrderSearchStore } from './customer-order-search';
templateUrl: 'customer-order.component.html',
styleUrls: ['customer-order.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [CustomerOrderSearchStore],
providers: [provideComponentStore(CustomerOrderSearchStore)],
})
export class CustomerOrderComponent implements OnInit {
@ViewChild(BreadcrumbComponent, { read: ElementRef }) breadcrumbRef: ElementRef<HTMLElement>;

View File

@@ -22,6 +22,7 @@ import { debounceTime, first, map, shareReplay, takeUntil, tap } from 'rxjs/oper
import { GoodsInListItemComponent } from './goods-in-list-item/goods-in-list-item.component';
import { GoodsInListStore } from './goods-in-list.store';
import { PickupShelfInNavigationService } from '@shared/services';
import { CacheService } from '@core/cache';
@Component({
selector: 'page-goods-in-list',
@@ -60,20 +61,21 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
private _onDestroy$ = new Subject();
private readonly SCROLL_POSITION_TOKEN = 'GOODS_IN_LIST_SCROLL_POSITION';
constructor(
private _breadcrumb: BreadcrumbService,
private _domainOmsService: DomainOmsService,
public store: GoodsInListStore,
private _router: Router,
private _route: ActivatedRoute,
private readonly _config: Config
private readonly _config: Config,
private _cache: CacheService
) {}
ngOnInit() {
this.store.setTake(Number(this._route.snapshot.queryParams.take ?? 25));
this._route.queryParams.pipe(takeUntil(this._onDestroy$), debounceTime(0)).subscribe(async (params) => {
const scrollPos = Number(params.scroll_position ?? 0);
// Initial Search - Always Search If No Params Are Set
if (
(Object.keys(params).length === 0 || this.store.results.length === 0) &&
@@ -82,7 +84,8 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
this.store.search({
cb: () => {
setTimeout(() => {
this.scrollContainer?.scrollTo(scrollPos);
this.scrollContainer?.scrollTo(this._getScrollPositionFromCache());
this._removeScrollPositionFromCache();
}, 0);
},
});
@@ -101,7 +104,8 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
this.store.search({
cb: () => {
setTimeout(() => {
this.scrollContainer?.scrollTo(scrollPos);
this.scrollContainer?.scrollTo(this._getScrollPositionFromCache());
this._removeScrollPositionFromCache();
}, 0);
},
});
@@ -117,12 +121,13 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
this._onDestroy$.next();
this._onDestroy$.complete();
this._addScrollPositionToCache();
this.updateBreadcrumb(this.store.filter.getQueryParams());
}
cleanupQueryParams(params: Record<string, string> = {}) {
const clean = { ...params };
delete clean['scroll_position'];
delete clean['take'];
delete clean['view'];
@@ -143,6 +148,21 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
this.listItems.changes.pipe(takeUntil(this._onDestroy$)).subscribe(() => this.registerEditSscDisabled());
}
private _removeScrollPositionFromCache(): void {
this._cache.delete({ processId: this._config.get('process.ids.goodsIn'), token: this.SCROLL_POSITION_TOKEN });
}
private _addScrollPositionToCache(): void {
this._cache.set<number>(
{ processId: this._config.get('process.ids.goodsIn'), token: this.SCROLL_POSITION_TOKEN },
this.scrollContainer?.scrollPos
);
}
private _getScrollPositionFromCache(): number {
return this._cache.get<number>({ processId: this._config.get('process.ids.goodsIn'), token: this.SCROLL_POSITION_TOKEN });
}
navigateToDetails(orderItem: OrderItemListItemDTO) {
if (this.editSsc) {
return;
@@ -184,7 +204,6 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
}
async updateBreadcrumb(queryParams: Record<string, string> | Params = this.store.filter?.getQueryParams()) {
const scroll_position = this.scrollContainer?.scrollPos;
const take = this._route?.snapshot?.queryParams?.take;
if (queryParams) {
@@ -192,7 +211,7 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
.getBreadcrumbsByKeyAndTags$(this._config.get('process.ids.goodsIn'), ['goods-in', 'list'])
.pipe(first())
.toPromise();
const params = { ...queryParams, scroll_position, take };
const params = { ...queryParams, take };
for (const crumb of crumbs) {
this._breadcrumb.patchBreadcrumb(crumb.id, {

View File

@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Router } from '@angular/router';
import { BreadcrumbService } from '@core/breadcrumb';
import { KeyValueDTOOfStringAndString, OrderItemListItemDTO } from '@swagger/oms';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
@@ -10,6 +10,7 @@ import { GoodsInRemissionPreviewStore } from './goods-in-remission-preview.store
import { Config } from '@core/config';
import { ToasterService } from '@shared/shell';
import { PickupShelfInNavigationService } from '@shared/services';
import { CacheService } from '@core/cache';
@Component({
selector: 'page-goods-in-remission-preview',
@@ -22,8 +23,6 @@ export class GoodsInRemissionPreviewComponent implements OnInit, OnDestroy {
private _pickupShelfInNavigationService = inject(PickupShelfInNavigationService);
@ViewChild(UiScrollContainerComponent) scrollContainer: UiScrollContainerComponent;
private _scrollPosition: number;
items$ = this._store.results$;
itemLength$ = this.items$.pipe(map((items) => items?.length));
@@ -52,14 +51,16 @@ export class GoodsInRemissionPreviewComponent implements OnInit, OnDestroy {
byCompartmentCodeFn = (item: OrderItemListItemDTO) =>
!!item.compartmentInfo ? `${item.compartmentCode}_${item.compartmentInfo}` : item.compartmentCode;
private readonly SCROLL_POSITION_TOKEN = 'REMISSION_PREVIEW_SCROLL_POSITION';
constructor(
private _breadcrumb: BreadcrumbService,
private _store: GoodsInRemissionPreviewStore,
private _route: ActivatedRoute,
private _router: Router,
private _modal: UiModalService,
private _config: Config,
private _toast: ToasterService
private _toast: ToasterService,
private _cache: CacheService
) {}
ngOnInit(): void {
@@ -71,9 +72,25 @@ export class GoodsInRemissionPreviewComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
this._onDestroy$.next();
this._onDestroy$.complete();
this._addScrollPositionToCache();
this.updateBreadcrumb();
}
private _removeScrollPositionFromCache(): void {
this._cache.delete({ processId: this._config.get('process.ids.goodsIn'), token: this.SCROLL_POSITION_TOKEN });
}
private _addScrollPositionToCache(): void {
this._cache.set<number>(
{ processId: this._config.get('process.ids.goodsIn'), token: this.SCROLL_POSITION_TOKEN },
this.scrollContainer?.scrollPos
);
}
private _getScrollPositionFromCache(): number {
return this._cache.get<number>({ processId: this._config.get('process.ids.goodsIn'), token: this.SCROLL_POSITION_TOKEN });
}
async createBreadcrumb() {
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
key: this._config.get('process.ids.goodsIn'),
@@ -93,7 +110,6 @@ export class GoodsInRemissionPreviewComponent implements OnInit, OnDestroy {
for (const crumb of crumbs) {
this._breadcrumb.patchBreadcrumb(crumb.id, {
name: crumb.name,
params: { scroll_position: this.scrollContainer?.scrollPos },
});
}
}
@@ -133,14 +149,11 @@ export class GoodsInRemissionPreviewComponent implements OnInit, OnDestroy {
this._store.searchResult$.pipe(takeUntil(this._onDestroy$)).subscribe(async (result) => {
await this.createBreadcrumb();
if (this._scrollPosition) {
this.scrollContainer?.scrollTo(Number(this._scrollPosition ?? 0));
this._scrollPosition = undefined;
}
this.scrollContainer?.scrollTo(this._getScrollPositionFromCache() ?? 0);
this._removeScrollPositionFromCache();
});
}
this._scrollPosition = this._route.snapshot.queryParams?.scroll_position;
this._store.search();
}

View File

@@ -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>
@@ -94,7 +97,7 @@
</ng-container>
</div>
<div class="text-right">
<span class="font-bold">{{ packageDetails.package.items }}</span> Exemplare
<span class="font-bold">{{ packageDetails?.package?.items ?? '-' }}</span> Exemplare
</div>
</div>
</div>

View File

@@ -126,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;
}

View File

@@ -18,7 +18,7 @@ import { PickUpShelfListItemComponent } from '../../shared/pickup-shelf-list-ite
import { Group, GroupByPipe } from '@ui/common';
import { UiSpinnerModule } from '@ui/spinner';
import { PickupShelfInNavigationService } from '@shared/services';
import { debounceTime, map } from 'rxjs/operators';
import { map } from 'rxjs/operators';
import { DBHOrderItemListItemDTO } from '@swagger/oms';
import { Observable, combineLatest, of } from 'rxjs';
import { PickupShelfDetailsStore, PickupShelfStore } from '../../store';
@@ -124,7 +124,8 @@ export class PickUpShelfInListComponent implements OnInit, AfterViewInit {
combineLatest([this.store.processId$, this._activatedRoute.queryParams])
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(([_, queryParams]) => {
if (!this.store.list.length || !isEqual(queryParams, this.store.filter.getQueryParams())) {
if (!this.store.list.length || !isEqual(queryParams, this.cleanupQueryParams(this.store.filter.getQueryParams()))) {
this.store.setQueryParams(queryParams);
this.store.fetchList();
}
@@ -148,6 +149,20 @@ export class PickUpShelfInListComponent implements OnInit, AfterViewInit {
this.scrollItemIntoView();
}
cleanupQueryParams(params: Record<string, string> = {}) {
const clean = { ...params };
for (const key in clean) {
if (Object.prototype.hasOwnProperty.call(clean, key)) {
if (clean[key] == undefined) {
delete clean[key];
}
}
}
return clean;
}
private _removeScrollPositionFromCache(): void {
this._cache.delete({ processId: this.store.processId, token: this.SCROLL_POSITION_TOKEN });
}

View File

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

View File

@@ -100,11 +100,11 @@ export class SharedNotificationChannelControlComponent extends ComponentStore<Sh
}
showChannelActionNameForEmailControl() {
return !!this.channelActionName && this.emailControl?.dirty;
return (!!this.channelActionName && this.emailControl?.dirty) || this.showSendAgainActionForEmail();
}
showChannelActionNameForMobileControl() {
return !!this.channelActionName && this.mobileControl?.dirty;
return (!!this.channelActionName && this.mobileControl?.dirty) || this.showSendAgainActionForMobile();
}
clear(control: FormControl) {
@@ -142,7 +142,7 @@ export class SharedNotificationChannelControlComponent extends ComponentStore<Sh
}
setNotificationChannels(notificationChannels: NotificationChannel[]) {
const notificationChannel = notificationChannels.reduce((val, current) => val | current, 0) as NotificationChannel;
const notificationChannel = this.getNotificationChannel(notificationChannels);
this.notificationChannelControl.setValue(notificationChannel);
this.notificationChannelControl.markAsDirty();
if (this.communicationDetails) {
@@ -150,6 +150,24 @@ export class SharedNotificationChannelControlComponent extends ComponentStore<Sh
}
}
getNotificationChannel(notificationChannels?: NotificationChannel[]) {
let nfc = notificationChannels ?? this.notificationChannels;
return nfc.reduce((val, current) => val | current, 0) as NotificationChannel;
}
// Ticket #4526 RD // Bearbeiten - erneut senden Button fehlt
// Auf den Pickup Shelf Edit Seiten soll der Erneut senden button immer ersichtlich sein
showSendAgainActionForEmail() {
return this.channelActionName === 'Erneut senden' && (this.getNotificationChannel() as Number) !== 3;
}
// Ticket #4526 RD // Bearbeiten - erneut senden Button fehlt
// Auf den Pickup Shelf Edit Seiten soll der Erneut senden button immer ersichtlich sein
// Wenn die Felder Email und SMS angehakt wurden, soll der Button nur einmal angezeigt werden
showSendAgainActionForMobile() {
return this.channelActionName === 'Erneut senden' && (this.getNotificationChannel() === 2 || this.getNotificationChannel() !== 1);
}
toggle(value?: boolean) {
this.patchState({ open: value ?? !this.get((s) => s.open) });
}

View File

@@ -10,7 +10,7 @@
<div class="w-28 page-package-list-item__estimated-delivery-date">
{{ package?.estimatedDeliveryDate | date }}
</div>
<div class="w-32 page-package-list-item__items-count">{{ package?.items }} <span class="font-normal">Exemplare</span></div>
<div class="w-32 page-package-list-item__items-count">{{ package?.items ?? '-' }} <span class="font-normal">Exemplare</span></div>
<div class="text-right grow">
<div
class="rounded inline-block px-4 text-white page-package-list-item__arrival-status whitespace-nowrap"

View File

@@ -107,10 +107,14 @@ export class ShellSideMenuComponent {
})
);
taskCalenderNavigation$ = this.getLastNavigationByProcessId(this._config.get('process.ids.taskCalendar'), {
path: ['/filiale', 'task-calendar'],
queryParams: {},
});
taskCalenderNavigation$ = this.getLastNavigationByProcessId(
this._config.get('process.ids.taskCalendar'),
{
path: ['/filiale', 'task-calendar'],
queryParams: {},
},
'/filiale/task-calendar'
);
assortmentNavigation$ = this.getLastNavigationByProcessId(this._config.get('process.ids.assortment'), {
path: ['/filiale', 'assortment'],
@@ -119,7 +123,8 @@ export class ShellSideMenuComponent {
pickUpShelfInRoutePath$ = this.getLastNavigationByProcessId(
this._config.get('process.ids.pickupShelf'),
this._pickUpShelfInNavigation.defaultRoute()
this._pickUpShelfInNavigation.defaultRoute(),
'/filiale/pickup-shelf'
);
// #4478 - RD // Abholfach - Routing löst Suche aus
@@ -188,10 +193,24 @@ export class ShellSideMenuComponent {
this._cdr.markForCheck();
}
getLastNavigationByProcessId(id: number, fallback?: { path: string[]; queryParams: any }) {
getLastNavigationByProcessId(id: number, fallback?: { path: string[]; queryParams: any }, pathContainsString?: string) {
return this._breadcrumbService.getBreadcrumbByKey$(id)?.pipe(
map((breadcrumbs) => {
const lastCrumb = breadcrumbs
.filter((breadcrumb) => {
/**
* #4532 - Der optionale Filter wurde hinzugefügt Breadcrumbs mit fehlerhaften Pfad auszuschließen.
* Dieser Filter kann entfernt werden, sobald die Breadcrumbs korrekt gesetzt werden. Jedoch konnte man bisher nicht feststellen,
* woher die fehlerhaften Breadcrumbs kommen.
*/
if (!pathContainsString) {
// Wenn kein Filter gesetzt ist, dann wird der letzte Breadcrumb zurückgegeben
return true;
}
const pathStr = Array.isArray(breadcrumb.path) ? breadcrumb.path.join('/') : breadcrumb.path;
return pathStr.includes(pathContainsString);
})
.filter((breadcrumb) => !breadcrumb?.params?.hasOwnProperty('view'))
.filter((breadcrumb) => !breadcrumb?.tags?.includes('reservation'))
.filter((breadcrumb) => !breadcrumb?.tags?.includes('cleanup'))

View File

@@ -5,10 +5,10 @@
"ng": "ng",
"start": "ng serve isa-app --ssl",
"test": "npm-run-all --serial \"test:* -- --watch=false --browsers=ChromeHeadlessNoSandbox --code-coverage\" --continue-on-error --print-label",
"test:isa-app": "ng test isa-app",
"*test:isa-app": "ng test isa-app",
"test:adapter-scan": "ng test @adapter/scan",
"test:cdn-product-image": "ng test @cdn/product-image",
"test:core": "ng test core",
"*test:core": "ng test core",
"*test:domain-availability": "ng test @domain/availability",
"*test:domain-cart": "ng test @domain/cart",
"*test:domain-catalog": "ng test @domain/catalog",
@@ -19,22 +19,22 @@
"*test:domain-oms": "ng test @domain/oms",
"*test:domain-package-inspection": "ng test @domain/package-inspection",
"*test:domain-printer": "ng test @domain/printer",
"test:domain-remission": "ng test @domain/remission",
"*test:domain-remission": "ng test @domain/remission",
"*test:domain-task-calendar": "ng test @domain/task-calendar",
"test:external": "ng test external",
"*test:hub-notifications": "ng test @hub/notifications",
"*test:isa-remission": "ng test @isa/remission",
"*test:modal-availabilities": "ng test @modal/availabilities",
"test:modal-history": "ng test @modal/history",
"*test:modal-history": "ng test @modal/history",
"*test:modal-images": "ng test @modal/images",
"test:modal-notifications": "ng test @modal/notifications",
"*test:modal-printer": "ng test @modal/printer",
"*test:modal-reorder": "ng test @modal/reorder",
"*test:modal-reviews": "ng test @modal/reviews",
"test:page": "ng test page",
"test:shared": "ng test shared",
"*test:page": "ng test page",
"*test:shared": "ng test shared",
"*test:shell-breadcrumb": "ng test @shell/breadcrumb",
"test:store-search-component-store": "ng test @store/search-component-store",
"*test:store-search-component-store": "ng test @store/search-component-store",
"*test:ui": "ng test ui",
"*test:utils": "ng test utils",
"*test:native-container": "ng test native-container",

View File

@@ -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"
],