mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
Merged PR 1215: #3062 #3051 Remission Breadcrumbs contain the correct queryParams, Remission Process Remembers Filters if Remission is started
#3062 #3051 Remission Breadcrumbs contain the correct queryParams, Remission Process Remembers Filters if Remission is started. Always load available Remission
This commit is contained in:
committed by
Andreas Schickinger
parent
42199c8cda
commit
9f0c81c20f
@@ -1,7 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { Config } from '@core/config';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@@ -27,7 +26,8 @@ export class CanActivateRemissionGuard implements CanActivate {
|
||||
this._applicationService.activateProcess(this._config.get('process.ids.remission'));
|
||||
|
||||
if (!!process?.data?.active && !state.url.includes(`/filiale/remission/${process?.data?.active}`)) {
|
||||
await this._router.navigate(['/filiale', 'remission', process?.data?.active, 'list']);
|
||||
const queryParams = process?.data?.queryParams ?? {};
|
||||
await this._router.navigate(['/filiale', 'remission', process?.data?.active, 'list'], { queryParams });
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<ui-icon icon="box_return" size="24px"></ui-icon>
|
||||
Abholfach
|
||||
</a>
|
||||
<a [routerLink]="['/filiale/remission']" routerLinkActive="active">
|
||||
<a [routerLink]="[remissionUrl$ | async]" [queryParams]="remissionQueryParams$ | async" routerLinkActive="active">
|
||||
<ui-icon icon="documents_refresh" size="24px"></ui-icon>
|
||||
Remission
|
||||
</a>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { Config } from '@core/config';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { DomainAvailabilityService } from '@domain/availability';
|
||||
import { DomainDashboardService } from '@domain/isa';
|
||||
@@ -56,13 +57,14 @@ describe('ShellComponent', () => {
|
||||
MockComponent(ShellProcessTabComponent),
|
||||
MockComponent(UiIconComponent),
|
||||
],
|
||||
mocks: [BreadcrumbService, DomainAvailabilityService, AuthService, DomainDashboardService],
|
||||
mocks: [BreadcrumbService, DomainAvailabilityService, AuthService, DomainDashboardService, Config],
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
applicationServiceMock = createSpyObject(ApplicationService);
|
||||
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
||||
applicationServiceMock.getProcesses$.and.returnValue(of([]));
|
||||
applicationServiceMock.getProcessById$.and.returnValue(of({ id: 4000 }));
|
||||
applicationServiceMock.getActivatedProcessId$.and.returnValue(of(undefined));
|
||||
applicationServiceMock.getLastActivatedProcessWithSectionAndType$.and.returnValue(of({}));
|
||||
applicationServiceMock.getLastActivatedProcessWithSection$.and.returnValue(of({}));
|
||||
@@ -225,6 +227,63 @@ describe('ShellComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('remissionProcess$', () => {
|
||||
it('should call _appService.getProcessById$() with Remission Id and return its value', async () => {
|
||||
applicationServiceMock.getProcessById$.and.returnValue(of({ id: 4000 }));
|
||||
await spectator.component.remissionProcess$.pipe(first()).toPromise();
|
||||
expect(applicationServiceMock.getProcessById$).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('remissionUrl$', () => {
|
||||
it('should return the correct url if process.data.active is available', async () => {
|
||||
const process = {
|
||||
id: 4000,
|
||||
data: {
|
||||
active: 9999,
|
||||
},
|
||||
};
|
||||
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
||||
const url = await spectator.component.remissionUrl$.pipe(first()).toPromise();
|
||||
expect(url).toBe('/filiale/remission/9999/list');
|
||||
});
|
||||
|
||||
it('should return the correct url if process.data.active is not available', async () => {
|
||||
const process = {
|
||||
id: 4000,
|
||||
data: {},
|
||||
};
|
||||
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
||||
const url = await spectator.component.remissionUrl$.pipe(first()).toPromise();
|
||||
expect(url).toBe('/filiale/remission');
|
||||
});
|
||||
});
|
||||
|
||||
describe('remissionQueryParams$', () => {
|
||||
it('should return the correct queryParams if process.data.active and process.data.queryParams are available', async () => {
|
||||
const process = {
|
||||
id: 4000,
|
||||
data: {
|
||||
active: 9999,
|
||||
queryParams: { filter: 'test' },
|
||||
},
|
||||
};
|
||||
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
||||
const queryParams = await spectator.component.remissionQueryParams$.pipe(first()).toPromise();
|
||||
expect(queryParams).toEqual(process.data.queryParams);
|
||||
});
|
||||
|
||||
it('should return the correct queryParams if process.data.active and process.data.queryParams are not available', async () => {
|
||||
const process = {
|
||||
id: 4000,
|
||||
data: {},
|
||||
};
|
||||
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
||||
const queryParams = await spectator.component.remissionQueryParams$.pipe(first()).toPromise();
|
||||
expect(queryParams).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setSection()', () => {
|
||||
it('should call _appService.setSection() with the argument section', async () => {
|
||||
await spectator.component.setSection('customer');
|
||||
|
||||
@@ -10,6 +10,7 @@ import { combineLatest } from 'rxjs';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { DomainAvailabilityService } from '@domain/availability';
|
||||
import { ShellProcessTabComponent } from '@shell/process';
|
||||
import { Config } from '@core/config';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shell',
|
||||
@@ -37,6 +38,22 @@ export class ShellComponent {
|
||||
return this.section$.pipe(switchMap((section) => this._appService.getProcesses$(section)));
|
||||
}
|
||||
|
||||
get remissionProcess$() {
|
||||
return this._appService.getProcessById$(this._config.get('process.ids.remission'));
|
||||
}
|
||||
|
||||
get remissionUrl$() {
|
||||
return this.remissionProcess$.pipe(
|
||||
map((process) => (process?.data?.active ? `/filiale/remission/${process.data.active}/list` : '/filiale/remission'))
|
||||
);
|
||||
}
|
||||
|
||||
get remissionQueryParams$() {
|
||||
return this.remissionProcess$.pipe(
|
||||
map((process) => (process?.data?.active && process?.data?.queryParams ? process.data.queryParams : {}))
|
||||
);
|
||||
}
|
||||
|
||||
get addProcessLabel$() {
|
||||
return combineLatest([this.section$, this.processes$]).pipe(
|
||||
map(([section, processes]) => (section === 'customer' && processes.length === 0 ? 'VORGANG STARTEN' : ''))
|
||||
@@ -53,6 +70,7 @@ export class ShellComponent {
|
||||
|
||||
constructor(
|
||||
private readonly _appService: ApplicationService,
|
||||
private readonly _config: Config,
|
||||
private readonly _notificationsHub: NotificationsHub,
|
||||
private readonly _modal: UiModalService,
|
||||
private readonly _router: Router,
|
||||
|
||||
@@ -23,6 +23,10 @@ export class AddProductComponent implements OnInit, OnDestroy {
|
||||
|
||||
hint$ = new Subject<string>();
|
||||
|
||||
get queryParams() {
|
||||
return this._activatedRoute?.snapshot?.queryParams;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _remiService: DomainRemissionService,
|
||||
private _modal: UiModalService,
|
||||
@@ -72,7 +76,7 @@ export class AddProductComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
modal.afterClosed$.pipe(takeUntil(this._onDestroy)).subscribe((result) => {
|
||||
if (result.data) {
|
||||
this._router.navigate(['..', 'list'], { relativeTo: this._activatedRoute });
|
||||
this._router.navigate(['..', 'list'], { relativeTo: this._activatedRoute, queryParams: this.queryParams });
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -102,6 +106,7 @@ export class AddProductComponent implements OnInit, OnDestroy {
|
||||
name: 'Wannennummer',
|
||||
path: '/filiale/remission/add-product',
|
||||
section: 'branch',
|
||||
params: this.queryParams,
|
||||
tags: ['remission', 'add-product'],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ export class RemissionFilterComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
applyFilter(filter: UiFilter) {
|
||||
this.store.setFilter(filter);
|
||||
this.store._filterChange$.next(true);
|
||||
this.store.applyFilter(filter);
|
||||
this.close.emit();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,7 @@ export class RemissionListComponentStore extends ComponentStore<RemissionState>
|
||||
|
||||
_sourceOrSupplierChange$ = new BehaviorSubject<boolean>(false);
|
||||
|
||||
_filterChange$ = new BehaviorSubject<boolean>(false);
|
||||
|
||||
scroll = new Subject<number>();
|
||||
private _filterChange$ = new BehaviorSubject<boolean>(false);
|
||||
|
||||
get processId() {
|
||||
return this._config.get('process.ids.remission');
|
||||
@@ -364,17 +362,36 @@ export class RemissionListComponentStore extends ComponentStore<RemissionState>
|
||||
);
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
this._cache.delete({ processId: String(this.processId) });
|
||||
}
|
||||
|
||||
clearItems() {
|
||||
this.setFetching(true);
|
||||
this.setSearchResult({ result: [], hits: 0 });
|
||||
}
|
||||
|
||||
async applyFilter(filter: UiFilter) {
|
||||
this._filterChange$.next(true);
|
||||
this.setFilter(filter);
|
||||
this.clearCache();
|
||||
await this._router.navigate([], {
|
||||
queryParams: {
|
||||
...filter.getQueryParams(),
|
||||
scroll_position: 0,
|
||||
},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
}
|
||||
|
||||
async setSupplier(supplier: SupplierDTO) {
|
||||
this._sourceOrSupplierChange$.next(true);
|
||||
this.setSearchResult({ result: [], hits: 0 });
|
||||
this.clearCache();
|
||||
await this._router.navigate([], {
|
||||
queryParams: {
|
||||
supplier: supplier.id,
|
||||
scroll_position: 0,
|
||||
},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
@@ -383,9 +400,11 @@ export class RemissionListComponentStore extends ComponentStore<RemissionState>
|
||||
async setSource(source: string) {
|
||||
this._sourceOrSupplierChange$.next(true);
|
||||
this.setSearchResult({ result: [], hits: 0 });
|
||||
this.clearCache();
|
||||
await this._router.navigate([], {
|
||||
queryParams: {
|
||||
source,
|
||||
scroll_position: 0,
|
||||
},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
|
||||
@@ -51,10 +51,15 @@
|
||||
</div>
|
||||
|
||||
<p *ngIf="!(return$ | async)" class="text-center mt-4">
|
||||
<a class="text-brand font-bold text-xl px-4 py-3" routerLink="../add-product">
|
||||
<a class="text-brand font-bold text-xl px-4 py-3" [queryParams]="queryParams$ | async" routerLink="../add-product">
|
||||
Artikel hinzufügen
|
||||
</a>
|
||||
<button type="button" class="text-brand font-bold text-xl px-4 py-3" routerLink="../shipping-documents">
|
||||
<button
|
||||
type="button"
|
||||
class="text-brand font-bold text-xl px-4 py-3"
|
||||
[queryParams]="queryParams$ | async"
|
||||
routerLink="../shipping-documents"
|
||||
>
|
||||
Warenbegleitscheine <span *ngIf="returnCount$ | async; let returnCount">({{ returnCount ?? 0 }})</span>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
@@ -61,6 +61,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
redirectTo: 'list',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -32,7 +32,6 @@ export class RemissionComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.addBreadcrumbIfNotExists();
|
||||
this.clearCache();
|
||||
|
||||
this._router.events
|
||||
?.pipe(
|
||||
@@ -64,15 +63,14 @@ export class RemissionComponent implements OnInit, OnDestroy {
|
||||
|
||||
async updateProcess() {
|
||||
const params = this._activatedRoute.snapshot.firstChild.params;
|
||||
const process = await this._applicationService.getProcessById$(this.processId).pipe(first()).toPromise();
|
||||
const queryParams = this._activatedRoute.snapshot.queryParams ?? {};
|
||||
if (!!params?.returnId) {
|
||||
if (process?.data?.active !== +params.returnId) {
|
||||
this._applicationService.patchProcess(this.processId, {
|
||||
closeable: false,
|
||||
data: { active: +params.returnId },
|
||||
});
|
||||
}
|
||||
this._applicationService.patchProcess(this.processId, {
|
||||
closeable: false,
|
||||
data: { active: +params.returnId, queryParams },
|
||||
});
|
||||
} else {
|
||||
this.clearCache();
|
||||
this._applicationService.patchProcess(this.processId, {
|
||||
closeable: true,
|
||||
data: {},
|
||||
|
||||
@@ -7,7 +7,7 @@ import { DomainRemissionService } from '@domain/remission';
|
||||
import { ComponentStore, tapResponse } from '@ngrx/component-store';
|
||||
import { ReturnDTO } from '@swagger/remi';
|
||||
import { NEVER, Observable } from 'rxjs';
|
||||
import { catchError, filter, map, shareReplay, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { catchError, filter, first, map, shareReplay, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { ShortReceiptNumberPipe } from '../../pipes/short-receipt-number.pipe';
|
||||
|
||||
export interface ShippingDocumentDetailsState {
|
||||
@@ -108,14 +108,16 @@ export class ShippingDocumentDetailsComponent extends ComponentStore<ShippingDoc
|
||||
this._breadcrumb.removeBreadcrumbsByKeyAndTags(this.processId, ['remission', 'finish-remission']);
|
||||
}
|
||||
|
||||
navigateBack() {
|
||||
async navigateBack() {
|
||||
const queryParams = await this.queryParams$.pipe(first()).toPromise();
|
||||
this.remissionStarted
|
||||
? this._router.navigate(['../list'], { relativeTo: this._activatedRoute })
|
||||
? this._router.navigate(['../list'], { relativeTo: this._activatedRoute, queryParams })
|
||||
: this._router.navigate(['..'], { relativeTo: this._activatedRoute });
|
||||
}
|
||||
|
||||
async addOrUpdateBreadcrumbIfNotExists(returnDto: ReturnDTO) {
|
||||
const packageNumber = returnDto?.receipts?.find((_) => true)?.data?.receiptNumber;
|
||||
const params = await this.queryParams$.pipe(first()).toPromise();
|
||||
if (packageNumber) {
|
||||
const shortPackageNumber = this._shortReceiptNumberPipe.transform(packageNumber);
|
||||
this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
|
||||
@@ -125,6 +127,7 @@ export class ShippingDocumentDetailsComponent extends ComponentStore<ShippingDoc
|
||||
? `/filiale/remission/${returnDto.id}/shipping-document`
|
||||
: `/filiale/remission/shipping-documents/${returnDto.id}`,
|
||||
section: 'branch',
|
||||
params,
|
||||
tags: ['remission', 'shipping-documents', 'details'],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { Config } from '@core/config';
|
||||
import { DomainRemissionService } from '@domain/remission';
|
||||
@@ -20,6 +21,7 @@ export class ShippingDocumentListComponent implements OnInit {
|
||||
private _remissionService: DomainRemissionService,
|
||||
private _breadcrumb: BreadcrumbService,
|
||||
private _config: Config,
|
||||
private _activatedRoute: ActivatedRoute,
|
||||
private readonly _dateAdapter: DateAdapter
|
||||
) {}
|
||||
|
||||
@@ -42,6 +44,7 @@ export class ShippingDocumentListComponent implements OnInit {
|
||||
name: 'Offene Warenbegleitscheine',
|
||||
path: '/filiale/remission/shipping-documents',
|
||||
section: 'branch',
|
||||
params: this._activatedRoute?.snapshot?.queryParams,
|
||||
tags: ['remission', 'shipping-documents'],
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user