Merge branch 'develop' into release/2.2

This commit is contained in:
Lorenz Hilpert
2023-02-21 10:26:01 +01:00
8 changed files with 98 additions and 38 deletions

View File

@@ -23,6 +23,7 @@
<h3 class="text-3xl text-center font-bold mt-8">Filter</h3>
<ui-filter
*ngIf="filterOverlay.isOpen"
#filter
class="mx-4"
[filter]="store.pendingFilter$ | async"

View File

@@ -26,9 +26,6 @@ export class PriceUpdateComponent implements OnInit {
hint$ = new Subject<string>();
@ViewChild(UiFilterComponent)
filter: UiFilterComponent;
@ViewChild(ShellFilterOverlayComponent)
filterOverlay: ShellFilterOverlayComponent;
@@ -142,7 +139,7 @@ export class PriceUpdateComponent implements OnInit {
closeFilterOverlay() {
this.hint$.next('');
this.filterOverlay.close();
this.store.restorePendingFilter();
this.filterOverlay.close();
}
}

View File

@@ -4,7 +4,7 @@ import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
import { Config } from '@core/config';
import { ToastService } from '@core/toast';
import { DomainPackageInspectionService } from '@domain/package-inspection';
import { NestedKeyValueDTOOfStringAndString, PackageDetailResponseDTO } from '@swagger/wws';
import { ArrivalStatus, NestedKeyValueDTOOfStringAndString, PackageDetailResponseDTO } from '@swagger/wws';
import { UiModalService } from '@ui/modal';
import { Observable, Subject } from 'rxjs';
import { first, map, shareReplay, startWith, switchMap, retry, tap } from 'rxjs/operators';
@@ -55,6 +55,16 @@ export class PackageDetailsComponent {
private _cdr: ChangeDetectorRef
) {}
private _getListPageBreadcrumb(): Promise<Breadcrumb> {
return this._breadcrumb
.getBreadcrumbsByKeyAndTags$(this.breadcrumbKey, ['filter'])
.pipe(
first(),
map((b) => b[0])
)
.toPromise();
}
async onActionClick(action: NestedKeyValueDTOOfStringAndString) {
if (action.command === 'NEXT') {
this.onNextAction(action);
@@ -62,7 +72,7 @@ export class PackageDetailsComponent {
try {
await this.changePackageStatus(action.value);
this.updatedToaster();
this.navigateToList();
this.navigateToList((+action.value as ArrivalStatus) || 0);
} catch (error) {
this._uiModal.error('Fehler beim Speichern der Daten.', error);
}
@@ -70,8 +80,21 @@ export class PackageDetailsComponent {
this.calculateListHeight();
}
navigateToList() {
this._router.navigate([`/filiale/package-inspection/packages`]);
async navigateToList(arrivalStatus: ArrivalStatus) {
const breadcrumb = await this._getListPageBreadcrumb();
if (breadcrumb) {
const packageId = await this.packageId$.pipe(first()).toPromise();
this._router.navigate([breadcrumb.path], {
queryParams: {
...breadcrumb.params,
updated_packageId: packageId,
updated_arrivalStatus: arrivalStatus,
},
});
} else {
this._router.navigate([`/filiale/package-inspection/packages`]);
}
}
updatedToaster() {
@@ -85,12 +108,8 @@ export class PackageDetailsComponent {
}
async changePackageStatus(status: string): Promise<void> {
try {
const packageDetails = await this.packageDetails$.pipe(first()).toPromise();
await this._packageInspectionService.changePackageStatus(packageDetails.package, status).toPromise();
} catch (error) {
console.error(error);
}
const packageDetails = await this.packageDetails$.pipe(first()).toPromise();
await this._packageInspectionService.changePackageStatus(packageDetails.package, status).toPromise();
}
async createBreadcrumbIfNotExists(details: PackageDetailResponseDTO): Promise<void> {

View File

@@ -3,7 +3,7 @@
<button
class="absolute right-0 top-0 h-14 rounded px-5 text-lg bg-cadet-blue grid grid-flow-col gap-2 items-center"
type="button"
(click)="filterOverlay.open()"
(click)="openFilter()"
>
<ui-svg-icon icon="filter-variant"></ui-svg-icon>
Filter
@@ -29,6 +29,7 @@
<h3 class="text-3xl text-center font-bold mt-8">Filter</h3>
<ui-filter
*ngIf="filterOverlay.isOpen"
#filter
class="mx-4"
[filter]="store.pendingFilter$ | async"
@@ -41,7 +42,7 @@
<button
type="button"
class="px-6 py-4 font-bold bg-white text-brand border-2 border-solid border-brand rounded-full"
(click)="store.resetPendingFilter()"
(click)="resetFilter()"
>
Filter zurücksetzen
</button>

View File

@@ -5,7 +5,7 @@ import { ListResponseArgsOfPackageDTO2, PackageDTO2, QuerySettingsDTO } from '@s
import { UiFilter } from '@ui/filter';
import { UiModalService } from '@ui/modal';
import { Observable, Subject } from 'rxjs';
import { debounceTime, filter, switchMap, tap, withLatestFrom } from 'rxjs/operators';
import { debounceTime, filter, switchMap, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
import { INITIAL_RESULT_COMPONENT_STATE, PackageResultComponentState } from './package-result.component.state';
@Injectable()
@@ -40,6 +40,8 @@ export class PackageResultComponentStore extends ComponentStore<PackageResultCom
onFetchPackagesResponse$ = this._onFetchPackagesResponse$.asObservable();
private _cancleFetchPackages$ = new Subject<void>();
constructor(private _packageInspectionService: DomainPackageInspectionService, private modal: UiModalService) {
super(INITIAL_RESULT_COMPONENT_STATE);
}
@@ -78,11 +80,16 @@ export class PackageResultComponentStore extends ComponentStore<PackageResultCom
switchMap(([options, filter]) =>
this._packageInspectionService
.queryPackagesResponse({ ...filter.getQueryToken(), take: options.take || 20 })
.pipe(tapResponse(this.onFetchPackagesResponse, this.onFetchError))
.pipe(takeUntil(this._cancleFetchPackages$), tapResponse(this.onFetchPackagesResponse, this.onFetchError))
)
)
);
cancelFetchPackages() {
this.setFetching(false);
this._cancleFetchPackages$.next();
}
paginatePackages = this.effect(($) =>
$.pipe(
debounceTime(250),

View File

@@ -5,13 +5,14 @@ import { CacheService } from '@core/cache';
import { Config } from '@core/config';
import { provideComponentStore } from '@ngrx/component-store';
import { ShellFilterOverlayComponent } from '@shell/filter-overlay';
import { ListResponseArgsOfPackageDTO2 } from '@swagger/wws';
import { ArrivalStatus, ListResponseArgsOfPackageDTO2 } from '@swagger/wws';
import { UiFilter, UiFilterComponent } from '@ui/filter';
import { isNumber, isString } from 'lodash';
import moment from 'moment';
import { asapScheduler, combineLatest, Subject, Subscription } from 'rxjs';
import { combineLatest, Subject, Subscription } from 'rxjs';
import { filter, first, map } from 'rxjs/operators';
import { PackageListComponent } from '../components/package-list';
import { PackageResultCacheData } from './package-result-ache-data';
import { PackageResultCacheData } from './package-result-cache-data';
import { PackageResultComponentStore } from './package-result.component.store';
@Component({
@@ -30,9 +31,6 @@ export class PackageResultComponent implements OnInit, AfterViewInit, OnDestroy
hint$ = new Subject<string>();
@ViewChild(UiFilterComponent)
filter: UiFilterComponent;
@ViewChild(ShellFilterOverlayComponent)
filterOverlay: ShellFilterOverlayComponent;
@@ -68,6 +66,14 @@ export class PackageResultComponent implements OnInit, AfterViewInit, OnDestroy
this.initFetchResponseSubscription();
}
hasUpdate(): { arrivalStatus: ArrivalStatus; packageId: string } | undefined {
const packageId = this._activatedRoute.snapshot.queryParams['updated_packageId'];
const arrivalStatus = this._activatedRoute.snapshot.queryParams['updated_arrivalStatus'];
if (!!packageId && !!arrivalStatus) {
return { arrivalStatus: Number(arrivalStatus) as ArrivalStatus, packageId: String(packageId) };
}
}
initFilterSubscription() {
const initialFilter$ = this.store.filter$.pipe(
filter((f) => f instanceof UiFilter),
@@ -78,6 +84,7 @@ export class PackageResultComponent implements OnInit, AfterViewInit, OnDestroy
const filterSub = combineLatest([initialFilter$, queryParams$]).subscribe(([filter, queryParams]) => {
const restoredFilter = this.restoreFilterFromQueryParams(filter, queryParams);
const restoredData = this.restoreResultsFromCache(restoredFilter);
this.createBreadcrumbIfNotExists(this.store.filter);
this.fetchPackages(restoredFilter, { keep: true, take: restoredData?.packages?.length });
});
@@ -105,6 +112,15 @@ export class PackageResultComponent implements OnInit, AfterViewInit, OnDestroy
restoreResultsFromCache(filter: UiFilter): PackageResultCacheData | undefined {
const data = this._cache.get<PackageResultCacheData>(filter.getQueryParams());
if (data) {
const update = this.hasUpdate();
if (update) {
const packageIndex = data.packages.findIndex((p) => p.id === update.packageId);
if (packageIndex > -1) {
data.packages[packageIndex].arrivalStatus = update.arrivalStatus;
}
}
this.store.setPackages(data.packages);
this.store.setTotal(data.total);
this.store.setFetching(false);
@@ -125,10 +141,11 @@ export class PackageResultComponent implements OnInit, AfterViewInit, OnDestroy
fetchPackages(filter: UiFilter, options: { keep?: boolean; take?: number } = {}) {
this.hint$.next('');
this.store.fetchPackages(options);
this.patchLocation(filter);
}
onFetchPackagesResponse = (response: ListResponseArgsOfPackageDTO2) => {
this.patchLocation(this.store.filter);
this.createBreadcrumbIfNotExists(this.store.filter);
if (response.error) {
console.error(response);
@@ -141,10 +158,19 @@ export class PackageResultComponent implements OnInit, AfterViewInit, OnDestroy
}
this.cacheData({});
this.filterOverlay.close();
this.closeFilterOverlay();
};
openFilter() {
this.store.cancelFetchPackages();
this.filterOverlay.open();
}
resetFilter() {
this.store.resetPendingFilter();
this.store.cancelFetchPackages();
}
async patchLocation(filter: UiFilter): Promise<void> {
this._router.navigate([], {
queryParams: filter.getQueryParams(),
@@ -213,8 +239,8 @@ export class PackageResultComponent implements OnInit, AfterViewInit, OnDestroy
}
closeFilterOverlay() {
this.filterOverlay.close();
this.store.restorePendingFilter();
this.filterOverlay.close();
}
allItemsRendered() {

View File

@@ -11,6 +11,7 @@ import {
EventEmitter,
Output,
} from '@angular/core';
import { Router } from '@angular/router';
import { DomainTaskCalendarService } from '@domain/task-calendar';
import { FileDTO } from '@swagger/checkout';
import { DisplayInfoDTO } from '@swagger/eis';
@@ -144,7 +145,8 @@ export class TaskInfoComponent implements OnChanges {
private domainTaskCalendarService: DomainTaskCalendarService,
private uiModal: UiModalService,
private clipboard: Clipboard,
@Optional() private modalRef: UiModalRef
@Optional() private modalRef: UiModalRef,
private router: Router
) {}
ngOnChanges({ info }: SimpleChanges): void {
@@ -208,15 +210,22 @@ export class TaskInfoComponent implements OnChanges {
}
openUrl(url: string) {
this.uiModal.open({
content: WebViewerModalComponent,
title: 'Digitale Titelvorschau',
data: url,
config: {
width: '1120px',
showScrollbarY: false,
},
});
// Wenn URL mit isa:// beginnt, dann soll der link nicht in dem WebViewerModal geöffnet werden,
// sondern auf der Seite selbst geöffnet werden.
if (url?.startsWith('isa://')) {
this.router.navigateByUrl(url.replace('isa://', '/'));
this.modalRef?.close();
} else {
this.uiModal.open({
content: WebViewerModalComponent,
title: 'Digitale Titelvorschau',
data: url,
config: {
width: '1120px',
showScrollbarY: false,
},
});
}
}
async addNote(note: string) {