Merged PR 1634: #4362 Scroll Position Handling, Bugfix between multiple open Shelf Out processes

#4362 Scroll Position Handling, Bugfix between multiple open Shelf Out processes
This commit is contained in:
Nino Righi
2023-10-16 07:44:55 +00:00
committed by Lorenz Hilpert
parent 4039ffdf20
commit 692a32f4d7
5 changed files with 151 additions and 21 deletions

View File

@@ -10,7 +10,7 @@ import { UiSpinnerModule } from '@ui/spinner';
import { OnInitDirective } from '@shared/directives/element-lifecycle';
import { PickupShelfInNavigationService } from '@shared/services';
import { BehaviorSubject, combineLatest } from 'rxjs';
import { map, shareReplay, tap } from 'rxjs/operators';
import { map, shareReplay } from 'rxjs/operators';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString } from '@swagger/oms';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';

View File

@@ -1,19 +1,32 @@
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnInit, TrackByFunction, inject } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
DestroyRef,
OnInit,
QueryList,
TrackByFunction,
ViewChild,
ViewChildren,
inject,
} from '@angular/core';
import { ActivatedRoute, NavigationStart, Router, RouterLink } from '@angular/router';
import { Filter, FilterModule } from '@shared/components/filter';
import { IconModule } from '@shared/components/icon';
import { PickUpShelfListItemComponent } from '../../shared/pickup-shelf-list-item/pickup-shelf-list-item.component';
import { UiScrollContainerModule } from '@ui/scroll-container';
import { UiScrollContainerComponent, UiScrollContainerModule } from '@ui/scroll-container';
import { GroupByPipe } from '@ui/common';
import { UiSpinnerModule } from '@ui/spinner';
import { PickupShelfInNavigationService } from '@shared/services';
import { map } from 'rxjs/operators';
import { debounceTime, map } from 'rxjs/operators';
import { DBHOrderItemListItemDTO } from '@swagger/oms';
import { Observable, combineLatest, of } from 'rxjs';
import { PickupShelfDetailsStore, PickupShelfStore } from '../../store';
import { isEqual } from 'lodash';
import { EnvironmentService } from '@core/environment';
import { CacheService } from '@core/cache';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'page-pickup-shelf-in-list',
@@ -35,11 +48,15 @@ import { EnvironmentService } from '@core/environment';
UiSpinnerModule,
],
})
export class PickUpShelfInListComponent implements OnInit {
export class PickUpShelfInListComponent implements OnInit, AfterViewInit {
@ViewChildren(PickUpShelfListItemComponent) listItems: QueryList<PickUpShelfListItemComponent>;
@ViewChild(UiScrollContainerComponent) scrollContainer: UiScrollContainerComponent;
private _pickupShelfInNavigationService = inject(PickupShelfInNavigationService);
store = inject(PickupShelfStore);
detailsStore = inject(PickupShelfDetailsStore);
destroyRef = inject(DestroyRef);
list$ = this.store.list$;
@@ -89,18 +106,67 @@ export class PickUpShelfInListComponent implements OnInit {
trackByFn: TrackByFunction<DBHOrderItemListItemDTO> = (index, item) => `${item.orderId}${item.orderItemId}${item.orderItemSubsetId}`;
private readonly SCROLL_POSITION_TOKEN = 'SHELF_IN_LIST_SCROLL_POSITION';
constructor(
private _environment: EnvironmentService,
private _activatedRoute: ActivatedRoute,
private _pickUpShelfInNavigation: PickupShelfInNavigationService
private _pickUpShelfInNavigation: PickupShelfInNavigationService,
private _cache: CacheService,
private _router: Router
) {}
ngOnInit() {
if (!this.store.list.length) {
this.store.fetchList();
this.store.processId$.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(150)).subscribe((_) => {
if (!this.store.list.length) {
this.store.fetchList();
}
const scrollPos = this._getScrollPositionFromCache();
if (!!scrollPos) {
setTimeout(() => {
if (this._activatedRoute.outlet === 'primary') {
}
this.scrollContainer?.scrollTo(scrollPos);
this._removeScrollPositionFromCache();
}, 150);
}
});
this._router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
if (event instanceof NavigationStart) {
this._addScrollPositionToCache();
}
});
}
ngAfterViewInit(): void {
this.scrollItemIntoView();
}
private _removeScrollPositionFromCache(): void {
this._cache.delete({ processId: this.store.processId, token: this.SCROLL_POSITION_TOKEN });
}
private _addScrollPositionToCache(): void {
if (this._activatedRoute.outlet === 'primary') {
this._cache.set<number>({ processId: this.store.processId, token: this.SCROLL_POSITION_TOKEN }, this.scrollContainer?.scrollPos);
}
}
private _getScrollPositionFromCache(): number {
return this._cache.get<number>({ processId: this.store.processId, token: this.SCROLL_POSITION_TOKEN });
}
// After Navigating to Result Side Outlet
scrollItemIntoView() {
setTimeout(() => {
const getPrimaryRouteParams = this._activatedRoute.parent?.children[0]?.snapshot?.params;
const item = this.listItems?.find((item) => item.item.orderId === Number(getPrimaryRouteParams?.orderId));
item?.scrollIntoView();
}, 150);
}
getItemDetailsLink(item: DBHOrderItemListItemDTO) {
return this._pickUpShelfInNavigation.detailRoute({
item: {

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy, inject, ContentChild, AfterViewInit } from '@angular/core';
import { Component, ChangeDetectionStrategy, inject, ContentChild } from '@angular/core';
import { PickupShelfDetailsBaseComponent } from '../../pickup-shelf-details-base.component';
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
import { PickUpShelfDetailsHeaderComponent } from '../../shared/pickup-shelf-details-header/pickup-shelf-details-header.component';
@@ -10,7 +10,6 @@ import { map } from 'rxjs/operators';
import { PickUpShelfDetailsTagsComponent } from '../../shared/pickup-shelf-details-tags/pickup-shelf-details-tags.component';
import { UiSpinnerModule } from '@ui/spinner';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { OnInitDirective } from '@shared/directives/element-lifecycle';
import { FormsModule } from '@angular/forms';

View File

@@ -1,22 +1,35 @@
import { Component, ChangeDetectionStrategy, inject, TrackByFunction, OnInit } from '@angular/core';
import {
Component,
ChangeDetectionStrategy,
inject,
TrackByFunction,
OnInit,
AfterViewInit,
ViewChildren,
QueryList,
ViewChild,
DestroyRef,
} from '@angular/core';
import { PickupShelfDetailsStore, PickupShelfStore } from '../../store';
import { AsyncPipe, NgFor, NgIf } from '@angular/common';
import { map } from 'rxjs/operators';
import { debounceTime, map } from 'rxjs/operators';
import { PickUpShelfOutNavigationService } from '@shared/services';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { ActivatedRoute, NavigationStart, Router, RouterLink } from '@angular/router';
import { IconModule } from '@shared/components/icon';
import { EnvironmentService } from '@core/environment';
import { Filter, FilterModule } from '@shared/components/filter';
import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
import { BehaviorSubject, Observable, combineLatest } from 'rxjs';
import { isEqual } from 'lodash';
import { PickUpShelfListItemComponent } from '../../shared/pickup-shelf-list-item/pickup-shelf-list-item.component';
import { UiScrollContainerModule } from '@ui/scroll-container';
import { UiScrollContainerComponent, UiScrollContainerModule } from '@ui/scroll-container';
import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString, OrderItemProcessingStatusValue } from '@swagger/oms';
import { Group, GroupByPipe } from '@shared/pipes/group-by';
import { UiSpinnerModule } from '@ui/spinner';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { PickupShelfListItemLoaderComponent } from '../../shared/pickup-shelf-list-item/pickup-shelf-list-item-loader.component';
import { ActionHandlerService } from '../../services/action-handler.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CacheService } from '@core/cache';
@Component({
selector: 'page-pcikup-shelf-out-list',
@@ -39,13 +52,17 @@ import { ActionHandlerService } from '../../services/action-handler.service';
PickupShelfListItemLoaderComponent,
],
})
export class PickupShelfOutListComponent implements OnInit {
export class PickupShelfOutListComponent implements OnInit, AfterViewInit {
@ViewChildren(PickUpShelfListItemComponent) listItems: QueryList<PickUpShelfListItemComponent>;
@ViewChild(UiScrollContainerComponent) scrollContainer: UiScrollContainerComponent;
private _pickupShelfOutNavigationService = inject(PickUpShelfOutNavigationService);
actionHandlerService = inject(ActionHandlerService);
store = inject(PickupShelfStore);
detailsStore = inject(PickupShelfDetailsStore);
destroyRef = inject(DestroyRef);
list$ = this.store.list$;
@@ -110,19 +127,67 @@ export class PickupShelfOutListComponent implements OnInit {
loadingFetchedActionButton$ = new BehaviorSubject<boolean>(false);
private readonly SCROLL_POSITION_TOKEN = 'SHELF_OUT_LIST_SCROLL_POSITION';
constructor(
private _environment: EnvironmentService,
private _activatedRoute: ActivatedRoute,
private _uiModal: UiModalService,
private _pickUpShelfOutNavigation: PickUpShelfOutNavigationService
private _pickUpShelfOutNavigation: PickUpShelfOutNavigationService,
private _cache: CacheService,
private _router: Router
) {}
ngOnInit() {
if (!this.store.list.length) {
this.store.fetchList();
this.processId$.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(150)).subscribe((_) => {
if (!this.store.list.length) {
this.store.fetchList();
}
const scrollPos = this._getScrollPositionFromCache();
if (!!scrollPos && this._activatedRoute.outlet === 'primary') {
setTimeout(() => {
this.scrollContainer?.scrollTo(scrollPos);
this._removeScrollPositionFromCache();
}, 150);
}
});
// OnDestroy would not trigger if switching between 2 Shelf Out processes
this._router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
if (event instanceof NavigationStart) {
this._addScrollPositionToCache();
}
});
}
ngAfterViewInit(): void {
this.scrollItemIntoView();
}
private _removeScrollPositionFromCache(): void {
this._cache.delete({ processId: this.store.processId, token: this.SCROLL_POSITION_TOKEN });
}
private _addScrollPositionToCache(): void {
if (this._activatedRoute.outlet === 'primary') {
this._cache.set<number>({ processId: this.store.processId, token: this.SCROLL_POSITION_TOKEN }, this.scrollContainer?.scrollPos);
}
}
private _getScrollPositionFromCache(): number {
return this._cache.get<number>({ processId: this.store.processId, token: this.SCROLL_POSITION_TOKEN });
}
// After Navigating to Result Side Outlet
scrollItemIntoView() {
setTimeout(() => {
const getPrimaryRouteParams = this._activatedRoute.parent?.children[0]?.snapshot?.params;
const item = this.listItems?.find((item) => item.item.orderId === Number(getPrimaryRouteParams?.orderId));
item?.scrollIntoView();
}, 150);
}
getSelectedItem$(item: DBHOrderItemListItemDTO) {
return this.store.selectedListItems$.pipe(
map((selectedListItems) => selectedListItems?.find((i) => i?.orderItemSubsetId === item?.orderItemSubsetId))

View File

@@ -241,7 +241,7 @@ export class PickupShelfStore extends ComponentStore<PickupShelfState> implement
) => {
this.patchState({ fetchingList: false, list: response.result, listHits: response.hits });
this._fetchListResponse.next({ processId, response, queryParams });
this._cacheService.set<ListResponseArgsOfDBHOrderItemListItemDTO>({ processId, queryParams }, response, { persist: true });
this._cacheService.set<ListResponseArgsOfDBHOrderItemListItemDTO>({ processId, queryToken: queryParams }, response, { persist: true });
};
private fetchListError = (err: any) => {