mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
Merge branch 'feature/#3265-Scroll-Position-Bug' into develop
This commit is contained in:
@@ -63,7 +63,6 @@ export class GoodsOutSearchFilterComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async applyFilter() {
|
||||
this._goodsOutSearchStore.clearResults();
|
||||
this._goodsOutSearchStore.setFilter(this.filter);
|
||||
this.message = undefined;
|
||||
|
||||
@@ -91,7 +90,7 @@ export class GoodsOutSearchFilterComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
});
|
||||
|
||||
this._goodsOutSearchStore.search({});
|
||||
this._goodsOutSearchStore.search({ clear: true });
|
||||
}
|
||||
|
||||
async updateBreadcrumb() {
|
||||
|
||||
@@ -6,8 +6,8 @@ import { ComponentStore, tapResponse } from '@ngrx/component-store';
|
||||
import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO, QuerySettingsDTO } from '@swagger/oms';
|
||||
import { UiFilter } from '@ui/filter';
|
||||
import { isResponseArgs } from '@utils/object';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { switchMap, mergeMap, withLatestFrom, filter, take, tap } from 'rxjs/operators';
|
||||
import { combineLatest, Observable, Subject } from 'rxjs';
|
||||
import { switchMap, mergeMap, withLatestFrom, filter, take, tap, debounceTime, first, map } from 'rxjs/operators';
|
||||
|
||||
export interface GoodsOutSearchState {
|
||||
defaultSettings?: QuerySettingsDTO;
|
||||
@@ -17,7 +17,6 @@ export interface GoodsOutSearchState {
|
||||
fetching: boolean;
|
||||
hits: number;
|
||||
results: OrderItemListItemDTO[];
|
||||
searchOptions?: { take?: number; skip?: number };
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@@ -58,13 +57,6 @@ export class GoodsOutSearchStore extends ComponentStore<GoodsOutSearchState> {
|
||||
|
||||
readonly queryParams$ = this.select((s) => s.queryParams);
|
||||
|
||||
get searchOptions() {
|
||||
return this.get((s) => s.searchOptions);
|
||||
}
|
||||
set searchOptions(searchOptions: { take?: number; skip?: number }) {
|
||||
this.patchState({ searchOptions });
|
||||
}
|
||||
|
||||
private _searchResultSubject = new Subject<ListResponseArgsOfOrderItemListItemDTO>();
|
||||
|
||||
readonly searchResult$ = this._searchResultSubject.asObservable();
|
||||
@@ -125,15 +117,15 @@ export class GoodsOutSearchStore extends ComponentStore<GoodsOutSearchState> {
|
||||
this.setFilter(filter);
|
||||
}
|
||||
|
||||
clearResults() {
|
||||
this.patchState({
|
||||
fetching: false,
|
||||
hits: 0,
|
||||
message: undefined,
|
||||
results: [],
|
||||
});
|
||||
this._searchResultClearedSubject.next();
|
||||
}
|
||||
// clearResults() {
|
||||
// this.patchState({
|
||||
// fetching: false,
|
||||
// hits: 0,
|
||||
// message: undefined,
|
||||
// results: [],
|
||||
// });
|
||||
// this._searchResultClearedSubject.next();
|
||||
// }
|
||||
|
||||
setQueryParams(queryParams: Record<string, string>) {
|
||||
this.patchState({ queryParams });
|
||||
@@ -143,60 +135,92 @@ export class GoodsOutSearchStore extends ComponentStore<GoodsOutSearchState> {
|
||||
}
|
||||
}
|
||||
|
||||
searchRequest(options?: { take?: number; skip?: number; reload?: boolean }) {
|
||||
return this.filter$.pipe(
|
||||
filter((f) => f instanceof UiFilter),
|
||||
take(1),
|
||||
mergeMap((filter) =>
|
||||
this._domainGoodsInService.searchWarenausgabe({
|
||||
...filter.getQueryToken(),
|
||||
skip: options.reload ? 0 : options?.skip ?? this.results.length,
|
||||
take: options.reload ? this.results.length : options?.take ?? 50,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
// searchRequest(options: { skip?: number; take?: number }) {
|
||||
// console.log('GoodsInSearchStore.searchRequest()', options);
|
||||
// return this.filter$.pipe(
|
||||
// filter((f) => f instanceof UiFilter),
|
||||
// take(1),
|
||||
// mergeMap((filter) => {
|
||||
// console.log('GoodsInSearchStore.searchRequest()', filter);
|
||||
// return this._domainGoodsInService.searchWarenausgabe({
|
||||
// ...filter.getQueryToken(),
|
||||
// skip: options.skip,
|
||||
// take: options.take,
|
||||
// });
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
|
||||
search = this.effect((options$: Observable<{ siletReload?: boolean }>) =>
|
||||
search = this.effect((options$: Observable<{ clear?: boolean; siletReload?: boolean }>) =>
|
||||
options$.pipe(
|
||||
tap((options) => {
|
||||
switchMap((options) => {
|
||||
return this.results$.pipe(
|
||||
map((results) => [options, results]),
|
||||
first()
|
||||
);
|
||||
}),
|
||||
switchMap(([options, results]) => {
|
||||
return this.filter$.pipe(
|
||||
filter((f) => f instanceof UiFilter),
|
||||
map((filter) => [options, results, filter]),
|
||||
first()
|
||||
);
|
||||
}),
|
||||
tap(([options, results, filter]: [{ clear?: boolean; siletReload?: boolean }, OrderItemListItemDTO[], UiFilter]) => {
|
||||
if (!options?.siletReload) {
|
||||
this.patchState({ fetching: true });
|
||||
}
|
||||
if (options?.clear) {
|
||||
this._searchResultClearedSubject.next();
|
||||
}
|
||||
}),
|
||||
withLatestFrom(this.results$),
|
||||
switchMap(([_options, _results]) => {
|
||||
const queryToken = this.filter?.getQueryToken();
|
||||
switchMap(([options, results, filter]) => {
|
||||
const queryToken = filter?.getQueryToken() ?? {};
|
||||
|
||||
if (queryToken && this._cache.get(queryToken)) {
|
||||
const cached = this._cache.get(queryToken);
|
||||
let cachedResultCount: number;
|
||||
|
||||
this.patchState(cached);
|
||||
if (options?.siletReload && this._cache.get(filter?.getQueryToken())) {
|
||||
const cachedResults = this._cache.get(queryToken);
|
||||
if (cachedResults?.results?.length > 0) {
|
||||
this.patchState(cachedResults);
|
||||
cachedResultCount = cachedResults.results.length;
|
||||
}
|
||||
}
|
||||
|
||||
return this.searchRequest({ ...this.searchOptions, reload: _options.siletReload }).pipe(
|
||||
if (options.clear) {
|
||||
queryToken.skip = 0;
|
||||
queryToken.take = 50;
|
||||
} else if (options.siletReload) {
|
||||
queryToken.skip = 0;
|
||||
queryToken.take = cachedResultCount || results.length || 50;
|
||||
} else {
|
||||
queryToken.skip = results.length;
|
||||
queryToken.take = 50;
|
||||
}
|
||||
|
||||
return this._domainGoodsInService.searchWarenausgabe(queryToken).pipe(
|
||||
tapResponse(
|
||||
(res) => {
|
||||
let results: OrderItemListItemDTO[] = [];
|
||||
if (_options.siletReload) {
|
||||
results = res.result;
|
||||
let _results: OrderItemListItemDTO[] = [];
|
||||
if (options.siletReload) {
|
||||
_results = res.result;
|
||||
} else if (options.clear) {
|
||||
_results = res.result;
|
||||
} else {
|
||||
results = [...(_results ?? []), ...(res.result ?? [])];
|
||||
_results = [...results, ...(res.result ?? [])];
|
||||
}
|
||||
|
||||
this.patchState({
|
||||
hits: res.hits,
|
||||
results,
|
||||
results: _results,
|
||||
fetching: false,
|
||||
});
|
||||
|
||||
if (queryToken) {
|
||||
this._cache.set(queryToken, {
|
||||
hits: res.hits,
|
||||
results,
|
||||
fetching: false,
|
||||
});
|
||||
}
|
||||
this._cache.set(filter?.getQueryToken(), {
|
||||
hits: res.hits,
|
||||
results: _results,
|
||||
fetching: false,
|
||||
});
|
||||
|
||||
this._searchResultSubject.next(res);
|
||||
},
|
||||
@@ -218,37 +242,37 @@ export class GoodsOutSearchStore extends ComponentStore<GoodsOutSearchState> {
|
||||
)
|
||||
);
|
||||
|
||||
reload = this.effect(($) =>
|
||||
$.pipe(
|
||||
tap((_) => this.patchState({ fetching: true })),
|
||||
withLatestFrom(this.results$),
|
||||
switchMap(([_, results]) =>
|
||||
this.searchRequest({ take: results?.length ?? 0, skip: 0 }).pipe(
|
||||
tapResponse(
|
||||
(res) => {
|
||||
this.patchState({
|
||||
hits: res.hits,
|
||||
results: res.result,
|
||||
fetching: false,
|
||||
});
|
||||
// reload = this.effect(($) =>
|
||||
// $.pipe(
|
||||
// tap((_) => this.patchState({ fetching: true })),
|
||||
// withLatestFrom(this.results$),
|
||||
// switchMap(([_, results]) =>
|
||||
// this.searchRequest({ reload: true }).pipe(
|
||||
// tapResponse(
|
||||
// (res) => {
|
||||
// this.patchState({
|
||||
// hits: res.hits,
|
||||
// results: res.result,
|
||||
// fetching: false,
|
||||
// });
|
||||
|
||||
this._searchResultSubject.next(res);
|
||||
},
|
||||
(err: Error) => {
|
||||
if (err instanceof HttpErrorResponse && isResponseArgs(err.error)) {
|
||||
this._searchResultSubject.next(err.error);
|
||||
} else {
|
||||
this._searchResultSubject.next({
|
||||
error: true,
|
||||
message: err.message,
|
||||
});
|
||||
}
|
||||
this.patchState({ fetching: false });
|
||||
console.error('GoodsInSearchStore.reload()', err);
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
// this._searchResultSubject.next(res);
|
||||
// },
|
||||
// (err: Error) => {
|
||||
// if (err instanceof HttpErrorResponse && isResponseArgs(err.error)) {
|
||||
// this._searchResultSubject.next(err.error);
|
||||
// } else {
|
||||
// this._searchResultSubject.next({
|
||||
// error: true,
|
||||
// message: err.message,
|
||||
// });
|
||||
// }
|
||||
// this.patchState({ fetching: false });
|
||||
// console.error('GoodsInSearchStore.reload()', err);
|
||||
// }
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// );
|
||||
}
|
||||
|
||||
@@ -79,7 +79,6 @@ export class GoodsOutSearchMainComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async search() {
|
||||
this._goodsOutSearchStore.clearResults();
|
||||
await this.updateQueryParams(this.processId);
|
||||
this.message = undefined;
|
||||
|
||||
@@ -103,8 +102,7 @@ export class GoodsOutSearchMainComponent implements OnInit, OnDestroy {
|
||||
this._cdr.markForCheck();
|
||||
});
|
||||
|
||||
this._goodsOutSearchStore.searchOptions = { take: 50, skip: 0 };
|
||||
this._goodsOutSearchStore.search({});
|
||||
this._goodsOutSearchStore.search({ clear: true });
|
||||
}
|
||||
|
||||
async updateBreadcrumb(processId: number, params: Record<string, string>) {
|
||||
|
||||
@@ -87,23 +87,48 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
});
|
||||
}
|
||||
|
||||
saveScrollPosition(processId: number, scrollPosition: number) {
|
||||
// console.log('saveScrollPosition', processId, scrollPosition);
|
||||
localStorage.setItem(`SCROLL_POSITION_${processId}`, JSON.stringify(scrollPosition));
|
||||
}
|
||||
|
||||
getScrollPosition(processId: number): number | undefined {
|
||||
// try {
|
||||
// throw new Error('test');
|
||||
// } catch (error) {
|
||||
// console.error(error);
|
||||
// }
|
||||
|
||||
const scroll_position = localStorage.getItem(`SCROLL_POSITION_${processId}`);
|
||||
console.log('getScrollPosition', processId, scroll_position ? JSON.parse(scroll_position) : undefined);
|
||||
return scroll_position ? JSON.parse(scroll_position) : undefined;
|
||||
}
|
||||
|
||||
// removeScrollPosition(processId: number) {
|
||||
// console.log('removeScrollPosition', processId);
|
||||
// localStorage.removeItem(`SCROLL_POSITION_${processId}`);
|
||||
// }
|
||||
|
||||
ngOnInit() {
|
||||
this.processId$
|
||||
.pipe(takeUntil(this._onDestroy$), debounceTime(1), withLatestFrom(this._activatedRoute.queryParams))
|
||||
.pipe(takeUntil(this._onDestroy$), debounceTime(10), withLatestFrom(this._activatedRoute.queryParams))
|
||||
.subscribe(([processId, params]) => {
|
||||
if (this.previousProcessId && this.previousProcessId !== processId) {
|
||||
this.saveScrollPosition(this.previousProcessId, this.scrollContainer.scrollPos);
|
||||
}
|
||||
|
||||
this._goodsOutSearchStore.setQueryParams(params);
|
||||
this.updateBreadcrumb(processId, params);
|
||||
|
||||
this.initInitialSearch(processId, params);
|
||||
this.createBreadcrumb(processId, params);
|
||||
this.removeBreadcrumbs(processId);
|
||||
if (this.previousProcessId !== processId) {
|
||||
this.initInitialSearch(processId, params);
|
||||
this.createBreadcrumb(processId, params);
|
||||
this.removeBreadcrumbs(processId);
|
||||
|
||||
this.previousProcessId = processId;
|
||||
|
||||
if (this.previousProcessId && processId !== this.previousProcessId) {
|
||||
this._goodsOutSearchStore.clearResults();
|
||||
this._goodsOutSearchStore.search({ siletReload: true });
|
||||
}
|
||||
|
||||
this.previousProcessId = processId;
|
||||
});
|
||||
|
||||
this._goodsOutSearchStore.searchResultCleared.pipe(takeUntil(this._onDestroy$)).subscribe((_) => this.clearSelectedItems());
|
||||
@@ -114,6 +139,7 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
this._onDestroy$.complete();
|
||||
|
||||
this.updateBreadcrumb(this.previousProcessId, this._goodsOutSearchStore.filter?.getQueryParams());
|
||||
this.saveScrollPosition(this.previousProcessId, this.scrollContainer.scrollPos);
|
||||
}
|
||||
|
||||
async removeBreadcrumbs(processId: number) {
|
||||
@@ -141,10 +167,22 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
});
|
||||
}
|
||||
|
||||
async updateBreadcrumb(processId: number, queryParams: Record<string, string>) {
|
||||
const scroll_position = this.scrollContainer?.scrollPos;
|
||||
const take = this._goodsOutSearchStore.results?.length;
|
||||
// async updateScrollPosition(processId: number) {
|
||||
// const scroll_position = this.scrollContainer?.scrollPos;
|
||||
|
||||
// const crumbs = await this._breadcrumb
|
||||
// .getBreadcrumbsByKeyAndTags$(processId, ['goods-out', 'results', 'filter'])
|
||||
// .pipe(first())
|
||||
// .toPromise();
|
||||
|
||||
// crumbs.forEach((crumb) => {
|
||||
// const params: Record<string, string> = { ...((crumb.params as Record<string, string>) ?? {}) };
|
||||
// params.scroll_position = String(scroll_position);
|
||||
// this._breadcrumb.patchBreadcrumb(crumb.id, { params });
|
||||
// });
|
||||
// }
|
||||
|
||||
async updateBreadcrumb(processId: number, queryParams: Record<string, string>) {
|
||||
if (queryParams) {
|
||||
const crumbs = await this._breadcrumb
|
||||
.getBreadcrumbsByKeyAndTags$(processId, ['goods-out', 'results', 'filter'])
|
||||
@@ -152,7 +190,7 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
.toPromise();
|
||||
|
||||
const name = queryParams.main_qs ? queryParams.main_qs : 'Alle Artikel';
|
||||
const params = { ...queryParams, scroll_position, take };
|
||||
const params = { ...queryParams };
|
||||
|
||||
for (const crumb of crumbs) {
|
||||
this._breadcrumb.patchBreadcrumb(crumb.id, {
|
||||
@@ -181,24 +219,24 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
if (result.hits === 1) {
|
||||
await this.navigateToDetails(processId, result.result[0]);
|
||||
} else {
|
||||
if (!!this._goodsOutSearchStore.searchOptions?.take) {
|
||||
this._goodsOutSearchStore.searchOptions = undefined;
|
||||
this.scrollContainer.scrollTo(Number(scroll_position ?? 0));
|
||||
const scrollPos = this.getScrollPosition(processId);
|
||||
if (scrollPos) {
|
||||
this.scrollContainer?.scrollTo(scrollPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this._goodsOutSearchStore.search({});
|
||||
}
|
||||
|
||||
const { scroll_position, take } = this._goodsOutSearchStore.queryParams;
|
||||
if (!!take && !!scroll_position) {
|
||||
this._goodsOutSearchStore.searchOptions = { take: Number(take) };
|
||||
}
|
||||
// const { scroll_position, take } = this._goodsOutSearchStore.queryParams;
|
||||
// if (!!take && !!scroll_position) {
|
||||
// this._goodsOutSearchStore.searchOptions = { take: Number(take) };
|
||||
// }
|
||||
}
|
||||
|
||||
async loadMore() {
|
||||
if (this._goodsOutSearchStore.hits > this._goodsOutSearchStore.results.length && !this._goodsOutSearchStore.fetching) {
|
||||
this.saveScrollPosition(this.previousProcessId, this.scrollContainer.scrollPos);
|
||||
this._goodsOutSearchStore.search({});
|
||||
}
|
||||
}
|
||||
@@ -249,7 +287,7 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
};
|
||||
try {
|
||||
await this._commandService.handleCommand(action.command, commandData);
|
||||
this._goodsOutSearchStore.reload();
|
||||
this._goodsOutSearchStore.search({ siletReload: true });
|
||||
this.clearSelectedItems();
|
||||
this.loadingFetchedActionButton$.next(false);
|
||||
} catch (error) {
|
||||
|
||||
26733
package-lock.json
generated
26733
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user