mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merge branch 'develop' into release/2.2
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user