mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
#1460 Remember Scroll Position, Implementing Dynamic Logic Start
This commit is contained in:
committed by
Lorenz Hilpert
parent
a1708ca5a5
commit
f4056d33a6
@@ -1,15 +1,14 @@
|
||||
import { Component, ChangeDetectionStrategy, OnInit, ChangeDetectorRef } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Component, ChangeDetectionStrategy, OnInit, ChangeDetectorRef, OnDestroy } from '@angular/core';
|
||||
import { ActivatedRoute, NavigationStart, Router } from '@angular/router';
|
||||
import { ApplicationService, ProcessService } from '@core/application';
|
||||
import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
|
||||
import { CartService } from '@domain/cart';
|
||||
import { CheckoutService } from '@domain/checkout';
|
||||
import { AddressHelper, AssignedPayerHelper, CrmCustomerService } from '@domain/crm';
|
||||
import { CustomerDTO, KeyValueDTOOfStringAndString } from '@swagger/crm';
|
||||
import { UiDebugModalComponent, UiModalService } from '@ui/modal';
|
||||
import { isArray } from '@utils/common';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
import { ShippingAddressHelper } from 'apps/domain/crm/src/lib/helpers/shipping-address.helper';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { first, map, shareReplay, switchMap, tap } from 'rxjs/operators';
|
||||
import { CantAddCustomerToCartModalComponent } from '../modals/cant-add-customer-to-cart-modal/cant-add-customer-to-cart.component';
|
||||
import { CantAddCustomerToCartData } from '../modals/cant-add-customer-to-cart-modal/cant-add-customer-to-cart.data';
|
||||
@@ -20,7 +19,7 @@ import { CantAddCustomerToCartData } from '../modals/cant-add-customer-to-cart-m
|
||||
styleUrls: ['customer-details.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CustomerDetailsComponent implements OnInit {
|
||||
export class CustomerDetailsComponent implements OnInit, OnDestroy {
|
||||
customerId$: Observable<number>;
|
||||
customer$: Observable<CustomerDTO>;
|
||||
|
||||
@@ -40,6 +39,8 @@ export class CustomerDetailsComponent implements OnInit {
|
||||
|
||||
private currentBreadcrumb: Breadcrumb;
|
||||
|
||||
scrollSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private customerDetailsService: CrmCustomerService,
|
||||
@@ -105,6 +106,15 @@ export class CustomerDetailsComponent implements OnInit {
|
||||
)
|
||||
);
|
||||
|
||||
this.scrollSubscription = this.router.events.subscribe((events) => {
|
||||
if (events instanceof NavigationStart) {
|
||||
if (!events?.url.includes('/customer/search') && !events?.url.includes('query')) {
|
||||
// Scrollposition im sessionStorage löschen wenn nicht zur suche zurück navigiert wird
|
||||
sessionStorage.removeItem('scrollPos');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.isB2b$ = this.customerType$.pipe(map((type) => type === 'b2b'));
|
||||
this.isWebshopOrGuest$ = this.customerType$.pipe(map((type) => type === 'webshop' || type === 'guest'));
|
||||
|
||||
@@ -114,6 +124,12 @@ export class CustomerDetailsComponent implements OnInit {
|
||||
this.createBreadcrumb();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (!!this.scrollSubscription) {
|
||||
this.scrollSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
async createBreadcrumb() {
|
||||
const customerId = await this.customerId$.pipe(first()).toPromise();
|
||||
|
||||
|
||||
@@ -6,19 +6,7 @@ import { CrmCustomerService } from '@domain/crm';
|
||||
import { PagedResult } from '@domain/defs';
|
||||
import { AutocompleteDTO, CustomerInfoDTO } from '@swagger/crm';
|
||||
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
|
||||
import {
|
||||
catchError,
|
||||
debounceTime,
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
first,
|
||||
map,
|
||||
shareReplay,
|
||||
switchMap,
|
||||
take,
|
||||
takeUntil,
|
||||
tap,
|
||||
} from 'rxjs/operators';
|
||||
import { catchError, debounceTime, distinctUntilChanged, filter, map, shareReplay, switchMap, take, takeUntil, tap } from 'rxjs/operators';
|
||||
import { CustomerSearchType, QueryFilter, ResultState } from './defs';
|
||||
import { cloneFilter, Filter, UiFilterMappingService } from '@ui/filter';
|
||||
import { NativeContainerService } from 'native-container';
|
||||
@@ -59,6 +47,8 @@ export abstract class CustomerSearch implements OnInit, OnDestroy {
|
||||
result: [],
|
||||
});
|
||||
|
||||
searchCompleted = new Subject();
|
||||
|
||||
public searchState$ = new BehaviorSubject<ResultState>('init');
|
||||
|
||||
get searchState(): ResultState {
|
||||
@@ -317,6 +307,8 @@ export abstract class CustomerSearch implements OnInit, OnDestroy {
|
||||
if (hits > 0) {
|
||||
this.filterActive$.next(false);
|
||||
}
|
||||
|
||||
this.searchCompleted.next();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export class CustomerSearchMainComponent implements OnInit, OnDestroy {
|
||||
ngOnInit() {
|
||||
this.detectDevice();
|
||||
this.initBreadcrumb();
|
||||
sessionStorage.removeItem('scrollPos');
|
||||
}
|
||||
|
||||
initBreadcrumb() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<div class="scroll-container" *ngIf="search.searchState$ | async as searchState">
|
||||
<div #scrollContainer class="scroll-container" *ngIf="search.searchState$ | async as searchState">
|
||||
<a
|
||||
[class.last]="last"
|
||||
[class.load]="searchState === 'fetching'"
|
||||
[routerLink]="['/customer', customer.id]"
|
||||
*ngFor="let customer of (search.searchResult$ | async)?.result; let last = last"
|
||||
*ngFor="let customer of customers$ | async; let last = last"
|
||||
uiIsInViewport
|
||||
[options]="viewportEnterOptions"
|
||||
(viewportEntered)="checkIfReload($event)"
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { NavigationStart, Router } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
|
||||
import { filter, take } from 'rxjs/operators';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { filter, map, take } from 'rxjs/operators';
|
||||
import { CustomerSearch } from '../customer-search.service';
|
||||
import { CustomerSearchType } from '../defs';
|
||||
|
||||
@Component({
|
||||
selector: 'page-customer-search-result',
|
||||
@@ -10,19 +13,80 @@ import { CustomerSearch } from '../customer-search.service';
|
||||
styleUrls: ['./search-results.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class CustomerSearchResultComponent implements OnInit, OnDestroy {
|
||||
export class CustomerSearchResultComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
@ViewChild('scrollContainer', { static: false }) scrollContainer: ElementRef<HTMLDivElement>;
|
||||
private _breadcrumb: Breadcrumb;
|
||||
customers$: Observable<CustomerSearchType[]>;
|
||||
scrollSubscription: Subscription;
|
||||
onLoadSubscription: Subscription;
|
||||
|
||||
protected readonly viewportEnterOptions: IntersectionObserverInit = {
|
||||
threshold: 0.75,
|
||||
};
|
||||
|
||||
constructor(private application: ApplicationService, private breadcrumb: BreadcrumbService, public search: CustomerSearch) {}
|
||||
constructor(
|
||||
private application: ApplicationService,
|
||||
private breadcrumb: BreadcrumbService,
|
||||
public search: CustomerSearch,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.customers$ = this.search.searchResult$.pipe(
|
||||
map((response) => {
|
||||
// console.log(response);
|
||||
return response.result;
|
||||
})
|
||||
);
|
||||
|
||||
// Safe current scroll position if navigating to Customer Details
|
||||
this.scrollSubscription = this.router.events.subscribe((events) => {
|
||||
if (events instanceof NavigationStart) {
|
||||
const customerId = Number.parseInt(events.url.replace(/\D/g, ''), 10);
|
||||
if (events?.url === `/customer/${customerId}`) {
|
||||
// Safe Scrollposition inside sessionStorage
|
||||
sessionStorage.setItem('scrollPos', `${this.scrollContainer.nativeElement.scrollTop}`);
|
||||
// - TESTING -
|
||||
// Safe Loaded customers
|
||||
// --> SAFE EDITED DATA TO LOADED CUSTOMERS ASWELL !!
|
||||
// this.search.searchResult$.subscribe((res) => {
|
||||
// console.log(res.result);
|
||||
// sessionStorage.setItem('preloadedCustomers', JSON.stringify(res.result));
|
||||
// });
|
||||
console.log(this.search.searchResult$.value.result);
|
||||
// sessionStorage.setItem('preloadedCustomers', JSON.stringify(this.search.searchResult$.value.result));
|
||||
} else {
|
||||
sessionStorage.removeItem('scrollPos');
|
||||
// sessionStorage.removeItem('preloadedCustomers');
|
||||
}
|
||||
}
|
||||
});
|
||||
this.initBreadcrumb();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
// Start scrolling to last remembered position
|
||||
this.scrollContainer.nativeElement.scrollTo(0, Number(sessionStorage.getItem('scrollPos')));
|
||||
|
||||
// ### SHOULD BE REMOVED IF CONTENT GETS PRELOADED ###
|
||||
// If content needs to be loaded, invoke the scroll again
|
||||
this.onLoadSubscription = this.search.searchCompleted.subscribe(() => {
|
||||
const container = this.scrollContainer.nativeElement.scrollTop;
|
||||
const storage = Number(sessionStorage.getItem('scrollPos'));
|
||||
if (container <= storage) {
|
||||
// Scroll to content
|
||||
this.scrollContainer.nativeElement.scrollTo(0, storage);
|
||||
} else if (storage <= 1100) {
|
||||
// Stop scrolling if needed content is loaded without loading more items
|
||||
this.onLoadSubscription.unsubscribe();
|
||||
} else {
|
||||
// Jump to content after items loaded and stop scrolling
|
||||
this.scrollContainer.nativeElement.scrollTo(0, storage);
|
||||
this.onLoadSubscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async initBreadcrumb() {
|
||||
await this.search.filtersLoaded$
|
||||
.pipe(
|
||||
@@ -55,6 +119,12 @@ export class CustomerSearchResultComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnDestroy() {
|
||||
this.search.searchState$.next('init');
|
||||
if (!!this.scrollSubscription) {
|
||||
this.scrollSubscription.unsubscribe();
|
||||
}
|
||||
if (!!this.onLoadSubscription) {
|
||||
this.onLoadSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
checkIfReload(target: HTMLElement): void {
|
||||
|
||||
Reference in New Issue
Block a user