Breadcrumb fue abholfach

This commit is contained in:
Lorenz Hilpert
2023-09-19 15:23:28 +02:00
parent 664053f231
commit ac656ddc04
12 changed files with 441 additions and 278 deletions

View File

@@ -1,8 +1,7 @@
import { Injectable, inject } from '@angular/core';
import { AbholfachService, ListResponseArgsOfDBHOrderItemListItemDTO, OrderItemProcessingStatusValue, QueryTokenDTO } from '@swagger/oms';
import { AbholfachService, ListResponseArgsOfDBHOrderItemListItemDTO, QueryTokenDTO } from '@swagger/oms';
import { PickupShelfIOService } from './pickup-shelf-io.service';
import { Observable, throwError } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class PickupShelfOutService extends PickupShelfIOService {
@@ -20,15 +19,12 @@ export class PickupShelfOutService extends PickupShelfIOService {
orderNumber?: string;
compartmentCode?: string;
}): Observable<ListResponseArgsOfDBHOrderItemListItemDTO> {
console.log('args', args);
if (!args.orderNumber && !args.compartmentCode) {
return throwError(
'PickupShelfOutService.getOrderItemsByOrderNumberOrCompartmentCode(): Either orderNumber or compartmentCode must be provided.'
);
}
console.log('args', args);
return this._abholfachService.AbholfachWarenausgabe({
input: {
qs: args.compartmentCode ?? args.orderNumber,

View File

@@ -1,21 +1,24 @@
import { DestroyRef, inject } from '@angular/core';
import { PickupShelfStore } from './store';
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router';
import { DestroyRef, Directive, OnInit, inject } from '@angular/core';
import { PickupShelfDetailsStore, PickupShelfStore } from './store';
import { ActivatedRoute, Router } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { log, logAsync } from '@utils/common';
import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
import { take } from 'rxjs/operators';
import { switchMap, take, tap, withLatestFrom } from 'rxjs/operators';
import { NavigationRoute } from '@shared/services';
import { DBHOrderItemListItemDTO } from '@swagger/oms';
import { DBHOrderItemListItemDTO, OrderItemProcessingStatusValue } from '@swagger/oms';
import { isEmpty } from 'lodash';
import { Observable, combineLatest, concat } from 'rxjs';
/**
* Enthält die gemeinsame Logik für die Suche und verbindet die Komponenten mit dem Store.
*/
export abstract class PickupShelfBaseComponent {
@Directive()
export abstract class PickupShelfBaseComponent implements OnInit {
protected destroyRef = inject(DestroyRef);
protected store = inject(PickupShelfStore);
protected listStore = inject(PickupShelfStore);
protected detailsStore = inject(PickupShelfDetailsStore);
protected router = inject(Router);
@@ -23,92 +26,70 @@ export abstract class PickupShelfBaseComponent {
protected breadcrumbService = inject(BreadcrumbService);
constructor() {
/**
* Wenn die Suche erfolgreich war, wird der Benutzer auf die Liste oder Detailseite des gefundenen Artikels weitergeleitet.
*/
this.store.fetchListResponse$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(async (response) => {
ngOnInit() {
this.regsiterFetchListResponseHandler();
this.regsiterProcessIdHandler();
this.registerQueryParamsHandler();
this.registerViewHandler();
}
regsiterFetchListResponseHandler() {
this.listStore.fetchListResponse$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(async (response) => {
/**
* Wenn die Suche erfolgreich war, wird der Benutzer auf die Liste oder Detailseite des gefundenen Artikels weitergeleitet.
*/
const queryParams = this.activatedRoute.snapshot.queryParams;
const filterQueryParams = this.store.filter.getQueryParams();
const filterQueryParams = this.listStore.filter.getQueryParams();
if (response.hits === 1) {
const detailsPath = await this.getPathForDetail(response.result[0]);
const detailsPath = await this.getPathForDetail(response.result[0]).pipe(take(1)).toPromise();
await this.router.navigate(detailsPath.path, { queryParams: { ...queryParams, ...filterQueryParams, ...detailsPath.queryParams } });
} else if (response.hits > 1) {
const listPath = await this.getPathFoList();
const listPath = await this.getPathFoListBreadcrumb().pipe(take(1)).toPromise();
await this.router.navigate(listPath.path, { queryParams: { ...queryParams, ...filterQueryParams, ...listPath.queryParams } });
} else {
// TODO: Fehlermeldung in Suchbox
await this.router.navigate([], { queryParams: { ...queryParams, ...filterQueryParams } });
}
});
}
/**
* Checkt ob sich die ProzessId in der URL geändert hat und aktualisiert den Store.
* Zusätzlich wird die Breadcrumb aktualisiert.
*/
this.router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
if (event instanceof NavigationEnd) {
this.runCheck();
regsiterProcessIdHandler() {
this.activatedRoute.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
const processIdStr = params.processId;
if (!processIdStr) {
return;
}
const processId = Number(processIdStr);
this.listStore.setProcessId(processId);
});
}
registerQueryParamsHandler() {
this.activatedRoute.queryParams.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((queryParams) => {
if (isEmpty(queryParams)) {
this.listStore.setQueryParams(undefined);
} else {
this.listStore.setQueryParams(queryParams);
}
});
this.runCheck(true);
}
protected async runCheck(firstCheck: boolean = false) {
this._checkAndUpdateProcessIdInStore();
this._checkAndUpdateQueryParamsInStore();
const crumb = await this._checkAndUpdateBreadcrumb();
if (firstCheck && ['list', 'filter'].includes(crumb)) {
this.store.fetchList();
}
}
/**
* Aktualiisiert die ProzessId im Store.
* @returns void
*/
@log
private _checkAndUpdateProcessIdInStore() {
const processIdStr = this.activatedRoute.snapshot.params.processId;
if (!processIdStr) {
return;
}
const processId = Number(processIdStr);
this.store.setProcessId(processId);
}
/**
* Update die QueryParams im Store.
* @returns void
*/
@log
private _checkAndUpdateQueryParamsInStore() {
const queryParams = this.activatedRoute.snapshot.queryParams;
if (isEmpty(queryParams)) {
this.store.setQueryParams(undefined);
} else {
this.store.setQueryParams(queryParams);
}
}
/**
* Aktualisiert die Breadcrumb.
*/
@logAsync
private async _checkAndUpdateBreadcrumb() {
const breadcrumb = this.findDataInActivatedRouteSnapshot(this.activatedRoute.snapshot, 'breadcrumb', 2);
await this._checkAndUpdateMainBreadcrumb(breadcrumb);
await this._checkAndUpdateListBreadcrumb(breadcrumb);
await this._checkAndUpdateFilterBreadcrumb(breadcrumb);
return breadcrumb;
registerViewHandler() {
this.activatedRoute.data
.pipe(
takeUntilDestroyed(this.destroyRef),
switchMap(({ view }) =>
this._checkAndUpdateMainBreadcrumb(view).pipe(
switchMap(() => this._checkAndUpdateListBreadcrumb(view)),
switchMap(() => this._checkAndUpdateFilterBreadcrumb(view)),
switchMap(() => this._checkAndUpdateDetailBreadcrumb(view))
)
)
)
.subscribe();
}
/**
@@ -116,152 +97,171 @@ export abstract class PickupShelfBaseComponent {
* @param tag Der gesuchte Tag
* @returns Breadcumb
*/
@logAsync
private async _getBreadcrumbByTag(tag: string) {
const breadcrumbs = await this.breadcrumbService
.getBreadcrumbsByKeyAndTags$(this.store.processId, ['pickup-shelf', tag])
.pipe(takeUntilDestroyed(this.destroyRef), take(1))
.toPromise();
return breadcrumbs[0];
private _getBreadcrumbByTag(tag: string) {
return this.breadcrumbService
.getBreadcrumbsByKeyAndTags$(this.listStore.processId, ['pickup-shelf', tag])
.pipe(takeUntilDestroyed(this.destroyRef), take(1));
}
/**
* Update die Main Breadcrumb.
* @param breadcrumb Der Aktuelle Breadcrumb Tag
*/
@logAsync
private async _checkAndUpdateMainBreadcrumb(breadcrumb: string) {
let mainBreadcrumb: Breadcrumb = await this._getBreadcrumbByTag('main');
abstract getNameForMainBreadcrumb(): Observable<string>;
if (!mainBreadcrumb) {
const name = await this.getNameForMainBreadcrumb();
const path = await this.getPathForMain();
mainBreadcrumb = {
key: this.store.processId,
name,
tags: ['pickup-shelf', 'main'],
path: path?.path,
section: 'customer',
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.addBreadcrumb(mainBreadcrumb);
} else {
const name = await this.getNameForMainBreadcrumb();
const path = await this.getPathForMain();
const changes: Partial<Breadcrumb> = {
name,
path: path?.path,
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.patchBreadcrumb(mainBreadcrumb.id, changes);
}
}
abstract getPathForMainBreadcrumb(): Observable<NavigationRoute>;
abstract getNameForMainBreadcrumb(): Promise<string>;
private _checkAndUpdateMainBreadcrumb(view: string) {
return combineLatest([this.getNameForMainBreadcrumb(), this.getPathForMainBreadcrumb()]).pipe(
withLatestFrom(this._getBreadcrumbByTag('main')),
tap(([[name, path], breadcrumbs]) => {
let mainBreadcrumb: Breadcrumb = breadcrumbs.pop();
abstract getPathForMain(): Promise<NavigationRoute>;
/**
* Update die List Breadcrumb.
* @param breadcrumb Der Aktuelle Breadcrumb Tag
*/
@logAsync
private async _checkAndUpdateListBreadcrumb(breadcrumb: string) {
let listBreadcrumb: Breadcrumb = await this._getBreadcrumbByTag('list');
const shouldHaveBreadcrumb = ['list', 'filter'].includes(breadcrumb);
if (shouldHaveBreadcrumb && !listBreadcrumb) {
const name = await this.getNameForListBreadcrumb();
const path = await this.getPathFoList();
listBreadcrumb = {
key: this.store.processId,
name,
tags: ['pickup-shelf', 'list'],
path: path?.path,
section: 'customer',
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.addBreadcrumb(listBreadcrumb);
} else if (shouldHaveBreadcrumb && listBreadcrumb) {
const name = await this.getNameForListBreadcrumb();
const path = await this.getPathFoList();
const changes: Partial<Breadcrumb> = {
name,
path: path?.path,
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.patchBreadcrumb(listBreadcrumb.id, changes);
} else if (!shouldHaveBreadcrumb && listBreadcrumb) {
this.breadcrumbService.removeBreadcrumb(listBreadcrumb.id);
}
}
abstract getNameForListBreadcrumb(): Promise<string>;
abstract getPathFoList(): Promise<NavigationRoute>;
/**
* Update die Filter Breadcrumb.
* @param breadcrumb Der Aktuelle Breadcrumb Tag
*/
@logAsync
private async _checkAndUpdateFilterBreadcrumb(breadcrumb: string) {
let filterBreadcrumb: Breadcrumb = await this._getBreadcrumbByTag('filter');
const shouldHaveBreadcrumb = ['filter'].includes(breadcrumb);
if (shouldHaveBreadcrumb && !filterBreadcrumb) {
const name = await this.getNameForFilterBreadcrumb();
const path = await this.getPathForFilter();
filterBreadcrumb = {
key: this.store.processId,
name,
tags: ['pickup-shelf', 'filter'],
path: path?.path,
section: 'customer',
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.addBreadcrumb(filterBreadcrumb);
} else if (shouldHaveBreadcrumb && filterBreadcrumb) {
const name = await this.getNameForFilterBreadcrumb();
const path = await this.getPathForFilter();
const changes: Partial<Breadcrumb> = {
name,
path: path?.path,
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.patchBreadcrumb(filterBreadcrumb.id, changes);
} else if (!shouldHaveBreadcrumb && filterBreadcrumb) {
this.breadcrumbService.removeBreadcrumb(filterBreadcrumb.id);
}
}
abstract getNameForFilterBreadcrumb(): Promise<string>;
abstract getPathForFilter(): Promise<NavigationRoute>;
@log
// TODO: Ort für auslagerung finden
findDataInActivatedRouteSnapshot(snapshot: ActivatedRouteSnapshot, data: string, depth: number) {
if (!snapshot) {
return;
}
if (snapshot.data[data]) {
return snapshot.data[data];
}
if (depth > 0) {
const children = snapshot.children;
for (const child of children) {
const result = this.findDataInActivatedRouteSnapshot(child, data, depth - 1);
if (result) {
return result;
if (!mainBreadcrumb) {
mainBreadcrumb = {
key: this.listStore.processId,
name,
tags: ['pickup-shelf', 'main'],
path: path?.path,
section: 'customer',
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.addBreadcrumb(mainBreadcrumb);
} else {
const changes: Partial<Breadcrumb> = {
name,
path: path?.path,
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.patchBreadcrumb(mainBreadcrumb.id, changes);
}
}
}
// remove excess breadcrumbs
breadcrumbs.forEach((breadcrumb) => {
this.breadcrumbService.removeBreadcrumb(breadcrumb.id);
});
})
);
}
abstract getPathForDetail(item: DBHOrderItemListItemDTO): Promise<NavigationRoute>;
abstract getNameForListBreadcrumb(): Observable<string>;
abstract getPathFoListBreadcrumb(): Observable<NavigationRoute>;
private _checkAndUpdateListBreadcrumb(view: string) {
return combineLatest([this.getNameForListBreadcrumb(), this.getPathFoListBreadcrumb()]).pipe(
withLatestFrom(this._getBreadcrumbByTag('list')),
tap(([[name, path], breadcrumbs]) => {
let listBreadcrumb: Breadcrumb = breadcrumbs.pop();
const shouldHaveBreadcrumb = ['list', 'filter', 'details'].includes(view);
if (shouldHaveBreadcrumb && !listBreadcrumb) {
listBreadcrumb = {
key: this.listStore.processId,
name,
tags: ['pickup-shelf', 'list'],
path: path?.path,
section: 'customer',
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.addBreadcrumb(listBreadcrumb);
} else if (shouldHaveBreadcrumb && listBreadcrumb) {
const changes: Partial<Breadcrumb> = {
name,
path: path?.path,
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.patchBreadcrumb(listBreadcrumb.id, changes);
} else if (!shouldHaveBreadcrumb && listBreadcrumb) {
this.breadcrumbService.removeBreadcrumb(listBreadcrumb.id);
}
// remove excess breadcrumbs
breadcrumbs.forEach((breadcrumb) => {
this.breadcrumbService.removeBreadcrumb(breadcrumb.id);
});
})
);
}
abstract getNameForFilterBreadcrumb(): Observable<string>;
abstract getPathForFilter(): Observable<NavigationRoute>;
private _checkAndUpdateFilterBreadcrumb(view: string) {
return combineLatest([this.getNameForFilterBreadcrumb(), this.getPathForFilter()]).pipe(
withLatestFrom(this._getBreadcrumbByTag('filter')),
tap(([[name, path], breadcrumbs]) => {
let filterBreadcrumb: Breadcrumb = breadcrumbs.pop();
const shouldHaveBreadcrumb = ['filter'].includes(view);
if (shouldHaveBreadcrumb && !filterBreadcrumb) {
filterBreadcrumb = {
key: this.listStore.processId,
name,
tags: ['pickup-shelf', 'filter'],
path: path?.path,
section: 'customer',
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.addBreadcrumb(filterBreadcrumb);
} else if (shouldHaveBreadcrumb && filterBreadcrumb) {
const changes: Partial<Breadcrumb> = {
name,
path: path?.path,
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.patchBreadcrumb(filterBreadcrumb.id, changes);
} else if (!shouldHaveBreadcrumb && filterBreadcrumb) {
this.breadcrumbService.removeBreadcrumb(filterBreadcrumb.id);
}
// remove excess breadcrumbs
breadcrumbs.forEach((breadcrumb) => {
this.breadcrumbService.removeBreadcrumb(breadcrumb.id);
});
})
);
}
abstract getNameForDetailBreadcrumb(): Observable<string>;
abstract getPathForDetail(item: DBHOrderItemListItemDTO): Observable<NavigationRoute>;
abstract getPathForDetailForDetailBreadcrumb(): Observable<NavigationRoute>;
private _checkAndUpdateDetailBreadcrumb(view: string) {
return combineLatest([this.getNameForDetailBreadcrumb(), this.getPathForDetailForDetailBreadcrumb()]).pipe(
withLatestFrom(this._getBreadcrumbByTag('details')),
tap(([[name, path], breadcrumbs]) => {
let filterBreadcrumb: Breadcrumb = breadcrumbs.pop();
const shouldHaveBreadcrumb = ['details'].includes(view);
if (shouldHaveBreadcrumb && !filterBreadcrumb) {
filterBreadcrumb = {
key: this.listStore.processId,
name,
tags: ['pickup-shelf', 'details'],
path: path?.path,
section: 'customer',
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.addBreadcrumb(filterBreadcrumb);
} else if (shouldHaveBreadcrumb && filterBreadcrumb) {
const changes: Partial<Breadcrumb> = {
name,
path: path?.path,
params: { ...path?.queryParams, ...this.activatedRoute.snapshot.queryParams },
};
this.breadcrumbService.patchBreadcrumb(filterBreadcrumb.id, changes);
} else if (!shouldHaveBreadcrumb && filterBreadcrumb) {
this.breadcrumbService.removeBreadcrumb(filterBreadcrumb.id);
}
// remove excess breadcrumbs
breadcrumbs.forEach((breadcrumb) => {
this.breadcrumbService.removeBreadcrumb(breadcrumb.id);
});
})
);
}
}

View File

@@ -7,6 +7,7 @@ import { PickupShelfIOService, PickupShelfService } from '@domain/pickup-shelf';
import { PickupShelfBaseComponent } from '../pickup-shelf-base.component';
import { NavigationRoute, PickupShelfInNavigationService } from '@shared/services';
import { DBHOrderItemListItemDTO } from '@swagger/oms';
import { Observable, of } from 'rxjs';
@Component({
selector: 'page-pickup-shelf-in',
@@ -21,29 +22,37 @@ import { DBHOrderItemListItemDTO } from '@swagger/oms';
export class PickupShelfInComponent extends PickupShelfBaseComponent {
private _pickupShelfInNavigationService = inject(PickupShelfInNavigationService);
async getPathForMain(): Promise<NavigationRoute> {
return this._pickupShelfInNavigationService.defaultRoute();
getPathForMainBreadcrumb(): Observable<NavigationRoute> {
return of(this._pickupShelfInNavigationService.defaultRoute());
}
async getNameForMainBreadcrumb(): Promise<string> {
return 'Wareneingang';
getNameForMainBreadcrumb(): Observable<string> {
return of('Wareneingang');
}
async getNameForListBreadcrumb(): Promise<string> {
return 'Liste';
getNameForListBreadcrumb(): Observable<string> {
return of('Liste');
}
async getPathFoList(): Promise<NavigationRoute> {
return this._pickupShelfInNavigationService.listRoute();
getPathFoListBreadcrumb(): Observable<NavigationRoute> {
return of(this._pickupShelfInNavigationService.listRoute());
}
async getNameForFilterBreadcrumb(): Promise<string> {
return 'Filter';
getNameForFilterBreadcrumb(): Observable<string> {
return of('Filter');
}
async getPathForFilter(): Promise<NavigationRoute> {
return this._pickupShelfInNavigationService.filterRoute();
getPathForFilter(): Observable<NavigationRoute> {
return of(this._pickupShelfInNavigationService.filterRoute());
}
async getPathForDetail(item: DBHOrderItemListItemDTO): Promise<NavigationRoute> {
return this._pickupShelfInNavigationService.detailRoute({ item });
getPathForDetail(item: DBHOrderItemListItemDTO): Observable<NavigationRoute> {
return of(this._pickupShelfInNavigationService.detailRoute({ item }));
}
getNameForDetailBreadcrumb(): Observable<string> {
throw new Error('Method not implemented.');
}
getPathForDetailForDetailBreadcrumb(): Observable<NavigationRoute> {
throw new Error('Method not implemented.');
}
}

View File

@@ -1,2 +1,2 @@
<shared-breadcrumb [key]="store.processId$ | async" [tags]="['pickup-shelf']"></shared-breadcrumb>
<shared-breadcrumb [key]="listStore.processId$ | async" [tags]="['pickup-shelf']"></shared-breadcrumb>
<shared-splitscreen></shared-splitscreen>

View File

@@ -7,8 +7,9 @@ import { PickupShelfIOService, PickupShelfOutService } from '@domain/pickup-shel
import { PickupShelfBaseComponent } from '../pickup-shelf-base.component';
import { NavigationRoute, PickupShelfOutNavigationService } from '@shared/services';
import { AsyncPipe } from '@angular/common';
import { DBHOrderItemListItemDTO } from '@swagger/oms';
import { logAsync } from '@utils/common';
import { DBHOrderItemListItemDTO, OrderItemProcessingStatusValue } from '@swagger/oms';
import { Observable, combineLatest, of } from 'rxjs';
import { filter, map } from 'rxjs/operators';
@Component({
selector: 'page-pickup-shelf-out',
@@ -27,38 +28,83 @@ import { logAsync } from '@utils/common';
export class PickupShelfOutComponent extends PickupShelfBaseComponent {
private _pickupShelfOutNavigationService = inject(PickupShelfOutNavigationService);
@logAsync
async getPathForMain(): Promise<NavigationRoute> {
return this._pickupShelfOutNavigationService.defaultRoute({ processId: this.store.processId });
constructor() {
super();
}
@logAsync
async getNameForMainBreadcrumb(): Promise<string> {
return 'Warenausgabe';
getPathForMainBreadcrumb(): Observable<NavigationRoute> {
return of(this._pickupShelfOutNavigationService.defaultRoute({ processId: this.listStore.processId }));
}
@logAsync
async getNameForListBreadcrumb(): Promise<string> {
return 'Liste';
getNameForMainBreadcrumb(): Observable<string> {
return of('Warenausgabe');
}
@logAsync
async getPathFoList(): Promise<NavigationRoute> {
return this._pickupShelfOutNavigationService.listRoute({ processId: this.store.processId });
getNameForListBreadcrumb(): Observable<string> {
return this.listStore.queryParams$.pipe(
map((queryParams) => {
if (queryParams?.main_qs) {
return queryParams.main_qs;
}
return 'Suche';
})
);
}
@logAsync
async getNameForFilterBreadcrumb(): Promise<string> {
return 'Filter';
getPathFoListBreadcrumb(): Observable<NavigationRoute> {
return of(this._pickupShelfOutNavigationService.listRoute({ processId: this.listStore.processId }));
}
@logAsync
async getPathForFilter(): Promise<NavigationRoute> {
return this._pickupShelfOutNavigationService.filterRoute({ processId: this.store.processId });
getNameForFilterBreadcrumb(): Observable<string> {
return of('Filter');
}
@logAsync
async getPathForDetail(item: DBHOrderItemListItemDTO): Promise<NavigationRoute> {
return this._pickupShelfOutNavigationService.detailRoute({ processId: this.store.processId, item });
getPathForFilter(): Observable<NavigationRoute> {
return of(this._pickupShelfOutNavigationService.filterRoute({ processId: this.listStore.processId }));
}
getNameForDetailBreadcrumb(): Observable<string> {
return combineLatest([this.detailsStore.order$, this.detailsStore.compartmentCode$]).pipe(
filter(([order, compartmentCode]) => !!order || !!compartmentCode),
map(([order, compartmentCode]) => {
if (compartmentCode) {
return compartmentCode;
}
return order.orderNumber;
})
);
}
getPathForDetail(item: DBHOrderItemListItemDTO): Observable<NavigationRoute> {
return of(
this._pickupShelfOutNavigationService.detailRoute({
processId: this.listStore.processId,
item: {
compartmentCode: item.compartmentCode,
orderId: item.orderId,
orderNumber: item.orderNumber,
processingStatus: item.processingStatus,
},
})
);
}
getPathForDetailForDetailBreadcrumb(): Observable<NavigationRoute> {
return combineLatest([this.detailsStore.order$, this.detailsStore.compartmentCode$, this.detailsStore.processingStatus$]).pipe(
filter(([order, compartmentCode, processingStatus]) => !!order && (!!compartmentCode || !!processingStatus)),
map(([order, compartmentCode, processingStatus]) => {
return this._pickupShelfOutNavigationService.detailRoute({
processId: this.listStore.processId,
item: {
orderId: order.id,
compartmentCode,
orderNumber: order.orderNumber,
processingStatus: processingStatus,
},
});
})
);
}
}

View File

@@ -5,21 +5,26 @@ import { PickupShelfOutMainComponent } from './pickup-shelf-out-main/pickup-shel
import { PickupShelfOutListComponent } from './pickup-shelf-out-list/pickup-shelf-out-list.component';
import { PickupShelfFilterComponent } from '../shared/pickup-shelf-filter/pickup-shelf-filter.component';
import { PickupShelfOutDetailsComponent } from './pickup-shelf-out-details/pickup-shelf-out-details.component';
import { viewResolver } from '../resolvers/view.resolver';
export const routes: Routes = [
{
path: '',
component: PickupShelfOutComponent,
resolve: {
view: viewResolver,
},
runGuardsAndResolvers: 'always',
children: [
{ path: '', component: PickupShelfOutMainComponent, data: { breadcrumb: 'main' } },
{ path: 'list', component: PickupShelfOutListComponent, data: { breadcrumb: 'list' } },
{ path: 'list/filter', component: PickupShelfFilterComponent, data: { breadcrumb: 'filter' } },
{ path: '', component: PickupShelfOutMainComponent, data: { view: 'main' } },
{ path: 'list', component: PickupShelfOutListComponent, data: { view: 'list' } },
{ path: 'list/filter', component: PickupShelfFilterComponent, data: { view: 'filter' } },
{
path: 'order/:orderId/:orderNumber/item/status/:orderItemProcessingStatus',
component: PickupShelfOutDetailsComponent,
data: { breadcrumb: 'details' },
data: { view: 'details' },
},
{ path: 'order/:orderId/compartment/:compartmentCode', component: PickupShelfOutDetailsComponent, data: { breadcrumb: 'details' } },
{ path: 'order/:orderId/compartment/:compartmentCode', component: PickupShelfOutDetailsComponent, data: { view: 'details' } },
// { path: 'main', outlet: 'side' },
// { path: 'list', outlet: 'side' },
],

View File

@@ -0,0 +1,27 @@
import { ActivatedRouteSnapshot, ResolveFn } from '@angular/router';
function findDataInActivatedRouteSnapshot(snapshot: ActivatedRouteSnapshot, data: string, depth: number) {
if (!snapshot) {
return;
}
if (snapshot.data[data]) {
return snapshot.data[data];
}
if (depth > 0) {
const children = snapshot.children;
for (const child of children) {
const result = findDataInActivatedRouteSnapshot(child, data, depth - 1);
if (result) {
return result;
}
}
}
}
export const viewResolver: ResolveFn<string> = (route: ActivatedRouteSnapshot) => {
const result = findDataInActivatedRouteSnapshot(route, 'view', 2);
console.log('viewResolver', result);
return result;
};

View File

@@ -1,4 +1,6 @@
import { uniq } from 'lodash';
import { PickupShelfDetailsState } from './pickup-shelf-details.state';
import { DBHOrderItemListItemDTO } from '@swagger/oms';
export const selectOrder = (s: PickupShelfDetailsState) => s.order;
@@ -10,8 +12,25 @@ export const selectFetchingOrderItems = (s: PickupShelfDetailsState) => s.fetchi
export const selectSelectedOrderItemProcessingStatus = (s: PickupShelfDetailsState) => s.selectedOrderItemProcessingStatus;
export const selectOrderItemsWithSelectedOrderItemProcessingStatus = (s: PickupShelfDetailsState) =>
s.orderItems?.filter((oi) => oi.processingStatus === s.selectedOrderItemProcessingStatus);
export const selectSelectedCompartmentCode = (s: PickupShelfDetailsState) => s.selectedCompartmentCode;
export const selectOrderItems = (s: PickupShelfDetailsState): DBHOrderItemListItemDTO[] => {
const compartmentCode = selectSelectedCompartmentCode(s);
const items = selectOrderItemsRaw(s);
if (compartmentCode) {
const compartmentInfo = selectCompartmentInfo(s);
return items?.filter((oi) => oi.compartmentCode === compartmentCode && oi.compartmentInfo === compartmentInfo);
}
const processingStatus = selectSelectedOrderItemProcessingStatus(s);
if (processingStatus) {
return items?.filter((oi) => oi.processingStatus === processingStatus);
}
return items;
};
export const selectCustomer = (s: PickupShelfDetailsState) => s.customer;
@@ -30,5 +49,35 @@ export const selectEstimatedDeliveryDate = (s: PickupShelfDetailsState) => {
};
export const selectCompartmentCode = (s: PickupShelfDetailsState) => {
throw new Error('not implemented');
const items = selectOrderItems(s);
const compartmentCodes = uniq(items?.filter((oi) => oi.compartmentCode)?.map((oi) => oi.compartmentCode));
if (compartmentCodes.length > 1) {
throw new Error('multiple compartments');
}
return compartmentCodes[0];
};
export const selectCompartmentInfo = (s: PickupShelfDetailsState) => {
const items = selectOrderItems(s);
const compartmentInfos = uniq(items?.filter((oi) => oi.compartmentInfo)?.map((oi) => oi.compartmentInfo));
if (compartmentInfos.length > 1) {
throw new Error('multiple compartments');
}
return compartmentInfos[0];
};
export const selectCompartment = (s: PickupShelfDetailsState) => {
const compartmentCode = selectCompartmentCode(s);
if (!compartmentCode) {
return undefined;
}
const compartmentInfo = selectCompartmentInfo(s);
return `${compartmentCode}_${compartmentInfo}`;
};

View File

@@ -9,6 +9,7 @@ export interface PickupShelfDetailsState {
orderItems?: DBHOrderItemListItemDTO[];
selectedOrderItemProcessingStatus?: OrderItemProcessingStatusValue;
selectedCompartmentCode?: string;
fetchingCustomer?: boolean;
customer?: CustomerInfoDTO;

View File

@@ -33,10 +33,10 @@ export class PickupShelfDetailsStore extends ComponentStore<PickupShelfDetailsSt
return this.get(Selectors.selectFetchingOrder);
}
orderItems$ = this.select(Selectors.selectOrderItemsWithSelectedOrderItemProcessingStatus);
orderItems$ = this.select(Selectors.selectOrderItems);
get orderItems() {
return this.get(Selectors.selectOrderItemsWithSelectedOrderItemProcessingStatus);
return this.get(Selectors.selectOrderItems);
}
fetchingOrderItems$ = this.select(Selectors.selectFetchingOrderItems);
@@ -45,9 +45,9 @@ export class PickupShelfDetailsStore extends ComponentStore<PickupShelfDetailsSt
return this.get(Selectors.selectFetchingOrderItems);
}
selectedOrderItemProcessingStatus$ = this.select(Selectors.selectSelectedOrderItemProcessingStatus);
processingStatus$ = this.select(Selectors.selectSelectedOrderItemProcessingStatus);
get selectedOrderItemProcessingStatus() {
get processingStatus() {
return this.get(Selectors.selectSelectedOrderItemProcessingStatus);
}
@@ -63,6 +63,24 @@ export class PickupShelfDetailsStore extends ComponentStore<PickupShelfDetailsSt
return this.get(Selectors.selectFetchingCustomer);
}
compartmentCode$ = this.select(Selectors.selectCompartmentCode);
get compartmentCode() {
return this.get(Selectors.selectCompartmentCode);
}
compartmentInfo$ = this.select(Selectors.selectCompartmentInfo);
get compartmentInfo() {
return this.get(Selectors.selectCompartmentInfo);
}
compartment$ = this.select(Selectors.selectCompartment);
get compartment() {
return this.get(Selectors.selectCompartment);
}
constructor() {
super({});
@@ -108,8 +126,8 @@ export class PickupShelfDetailsStore extends ComponentStore<PickupShelfDetailsSt
)
);
private beforeFetchOrderItems = () => {
this.patchState({ fetchingOrderItems: true, orderItems: [] });
private beforeFetchOrderItems = ({ compartmentCode }: { orderNumber?: string; compartmentCode?: string }) => {
this.patchState({ fetchingOrderItems: true, orderItems: [], selectedCompartmentCode: compartmentCode });
};
private fetchOrderItemsSuccess = (res: ListResponseArgsOfDBHOrderItemListItemDTO) => {

View File

@@ -40,6 +40,12 @@ export class PickupShelfStore extends ComponentStore<PickupShelfState> implement
readonly list$ = this.select(Selectors.selectList);
readonly queryParams$ = this.select(Selectors.selectQueryParams);
get queryParams() {
return this.get(Selectors.selectQueryParams);
}
get list() {
return this.get(Selectors.selectList);
}

View File

@@ -1,7 +1,7 @@
import { Injectable, inject } from '@angular/core';
import { NavigationRoute } from './navigation-route';
import { Router } from '@angular/router';
import { DBHOrderItemListItemDTO } from '@swagger/oms';
import { DBHOrderItemListItemDTO, OrderItemProcessingStatusValue } from '@swagger/oms';
@Injectable({ providedIn: 'root' })
export class PickupShelfOutNavigationService {
@@ -49,7 +49,13 @@ export class PickupShelfOutNavigationService {
};
}
detailRoute({ processId, item }: { processId?: number; item: DBHOrderItemListItemDTO }): NavigationRoute {
detailRoute({
processId,
item,
}: {
processId?: number;
item: { orderId: number; orderNumber: string; compartmentCode: string; processingStatus: OrderItemProcessingStatusValue };
}): NavigationRoute {
let path: any[];
if (item.compartmentCode) {