mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Abholfach Infrastruktur - WE und WA
This commit is contained in:
@@ -86,6 +86,28 @@ export class ApplicationService {
|
||||
return this.getProcessById$(processId).pipe(map((process) => process?.data?.selectedBranch));
|
||||
}
|
||||
|
||||
readonly REGEX_PROCESS_NAME = /^Vorgang \d+$/;
|
||||
|
||||
async createCustomerProcess(processId?: number): Promise<ApplicationProcess> {
|
||||
const processes = await this.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
const processIds = processes.filter((x) => this.REGEX_PROCESS_NAME.test(x.name)).map((x) => +x.name.split(' ')[1]);
|
||||
|
||||
const maxId = processIds.length > 0 ? Math.max(...processIds) : 0;
|
||||
|
||||
const process: ApplicationProcess = {
|
||||
id: processId ?? Date.now(),
|
||||
type: 'cart',
|
||||
name: `Vorgang ${maxId + 1}`,
|
||||
section: 'customer',
|
||||
closeable: true,
|
||||
};
|
||||
|
||||
await this.createProcess(process);
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
async createProcess(process: ApplicationProcess) {
|
||||
const existingProcess = await this.getProcessById$(process?.id).pipe(first()).toPromise();
|
||||
if (existingProcess?.id === process?.id) {
|
||||
|
||||
16
apps/domain/pickup-shelf/src/lib/pickup-shelf-in.service.ts
Normal file
16
apps/domain/pickup-shelf/src/lib/pickup-shelf-in.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { AbholfachService, QueryTokenDTO } from '@swagger/oms';
|
||||
import { PickupShelfIOService } from './pickup-shelf-io.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PickupShelfService extends PickupShelfIOService {
|
||||
private _abholfachService = inject(AbholfachService);
|
||||
|
||||
getQuerySettings() {
|
||||
return this._abholfachService.AbholfachWareneingangQuerySettings();
|
||||
}
|
||||
|
||||
search(queryToken: QueryTokenDTO) {
|
||||
return this._abholfachService.AbholfachWareneingang(queryToken);
|
||||
}
|
||||
}
|
||||
10
apps/domain/pickup-shelf/src/lib/pickup-shelf-io.service.ts
Normal file
10
apps/domain/pickup-shelf/src/lib/pickup-shelf-io.service.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ListResponseArgsOfDBHOrderItemListItemDTO, QueryTokenDTO, ResponseArgsOfQuerySettingsDTO } from '@swagger/oms';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export abstract class PickupShelfIOService {
|
||||
abstract getQuerySettings(): Observable<ResponseArgsOfQuerySettingsDTO>;
|
||||
|
||||
abstract search(queryToken: QueryTokenDTO): Observable<ListResponseArgsOfDBHOrderItemListItemDTO>;
|
||||
}
|
||||
16
apps/domain/pickup-shelf/src/lib/pickup-shelf-out.service.ts
Normal file
16
apps/domain/pickup-shelf/src/lib/pickup-shelf-out.service.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { AbholfachService, QueryTokenDTO } from '@swagger/oms';
|
||||
import { PickupShelfIOService } from './pickup-shelf-io.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PickupShelfOutService extends PickupShelfIOService {
|
||||
private _abholfachService = inject(AbholfachService);
|
||||
|
||||
getQuerySettings() {
|
||||
return this._abholfachService.AbholfachWarenausgabeQuerySettings();
|
||||
}
|
||||
|
||||
search(queryToken: QueryTokenDTO) {
|
||||
return this._abholfachService.AbholfachWarenausgabe(queryToken);
|
||||
}
|
||||
}
|
||||
4
apps/domain/pickup-shelf/src/lib/pickup-shelf.service.ts
Normal file
4
apps/domain/pickup-shelf/src/lib/pickup-shelf.service.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PickupShelfInService {}
|
||||
4
apps/domain/pickup-shelf/src/public-api.ts
Normal file
4
apps/domain/pickup-shelf/src/public-api.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './lib/pickup-shelf-in.service';
|
||||
export * from './lib/pickup-shelf-io.service';
|
||||
export * from './lib/pickup-shelf-out.service';
|
||||
export * from './lib/pickup-shelf.service';
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isDevMode, NgModule } from '@angular/core';
|
||||
import { inject, isDevMode, NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import {
|
||||
CanActivateCartGuard,
|
||||
@@ -22,6 +22,9 @@ import { MainComponent } from './main.component';
|
||||
import { PreviewComponent } from './preview';
|
||||
import { BranchSectionResolver, CustomerSectionResolver, ProcessIdResolver } from './resolvers';
|
||||
import { TokenLoginComponent, TokenLoginModule } from './token-login';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { ProcessIdGuard } from './guards/process-id.guard';
|
||||
import { ActivateProcessIdGuard } from './guards/activate-process-id.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -36,111 +39,116 @@ const routes: Routes = [
|
||||
canActivate: [IsAuthenticatedGuard],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
canActivate: [],
|
||||
path: 'kunde',
|
||||
component: MainComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'kunde',
|
||||
component: MainComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
loadChildren: () => import('@page/dashboard').then((m) => m.DashboardModule),
|
||||
},
|
||||
{
|
||||
path: 'product',
|
||||
loadChildren: () => import('@page/catalog').then((m) => m.PageCatalogModule),
|
||||
canActivate: [CanActivateProductGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/product',
|
||||
loadChildren: () => import('@page/catalog').then((m) => m.PageCatalogModule),
|
||||
canActivate: [CanActivateProductWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'order',
|
||||
loadChildren: () => import('@page/customer-order').then((m) => m.CustomerOrderModule),
|
||||
canActivate: [CanActivateCustomerOrdersGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/order',
|
||||
loadChildren: () => import('@page/customer-order').then((m) => m.CustomerOrderModule),
|
||||
canActivate: [CanActivateCustomerOrdersWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'customer',
|
||||
loadChildren: () => import('@page/customer').then((m) => m.CustomerModule),
|
||||
canActivate: [CanActivateCustomerGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/customer',
|
||||
loadChildren: () => import('@page/customer').then((m) => m.CustomerModule),
|
||||
canActivate: [CanActivateCustomerWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'cart',
|
||||
loadChildren: () => import('@page/checkout').then((m) => m.PageCheckoutModule),
|
||||
canActivate: [CanActivateCartGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/cart',
|
||||
loadChildren: () => import('@page/checkout').then((m) => m.PageCheckoutModule),
|
||||
canActivate: [CanActivateCartWithProcessIdGuard],
|
||||
},
|
||||
{
|
||||
path: 'goods/out',
|
||||
loadChildren: () => import('@page/goods-out').then((m) => m.GoodsOutModule),
|
||||
canActivate: [CanActivateGoodsOutGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/goods/out',
|
||||
loadChildren: () => import('@page/goods-out').then((m) => m.GoodsOutModule),
|
||||
canActivate: [CanActivateGoodsOutWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{ path: '**', redirectTo: 'dashboard', pathMatch: 'full' },
|
||||
],
|
||||
resolve: { section: CustomerSectionResolver },
|
||||
path: 'dashboard',
|
||||
loadChildren: () => import('@page/dashboard').then((m) => m.DashboardModule),
|
||||
},
|
||||
{
|
||||
path: 'filiale',
|
||||
component: MainComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'task-calendar',
|
||||
loadChildren: () => import('@page/task-calendar').then((m) => m.PageTaskCalendarModule),
|
||||
canActivate: [CanActivateTaskCalendarGuard],
|
||||
},
|
||||
{
|
||||
path: 'goods/in',
|
||||
loadChildren: () => import('@page/goods-in').then((m) => m.GoodsInModule),
|
||||
canActivate: [CanActivateGoodsInGuard],
|
||||
},
|
||||
{
|
||||
path: 'remission',
|
||||
loadChildren: () => import('@page/remission').then((m) => m.PageRemissionModule),
|
||||
canActivate: [CanActivateRemissionGuard],
|
||||
},
|
||||
{
|
||||
path: 'package-inspection',
|
||||
loadChildren: () => import('@page/package-inspection').then((m) => m.PackageInspectionModule),
|
||||
canActivate: [CanActivatePackageInspectionGuard],
|
||||
},
|
||||
{
|
||||
path: 'assortment',
|
||||
loadChildren: () => import('@page/assortment').then((m) => m.AssortmentModule),
|
||||
canActivate: [CanActivateAssortmentGuard],
|
||||
},
|
||||
{ path: '**', redirectTo: 'task-calendar', pathMatch: 'full' },
|
||||
],
|
||||
resolve: { section: BranchSectionResolver },
|
||||
path: 'product',
|
||||
loadChildren: () => import('@page/catalog').then((m) => m.PageCatalogModule),
|
||||
canActivate: [CanActivateProductGuard],
|
||||
},
|
||||
{ path: '**', redirectTo: 'kunde', pathMatch: 'full' },
|
||||
{
|
||||
path: ':processId/product',
|
||||
loadChildren: () => import('@page/catalog').then((m) => m.PageCatalogModule),
|
||||
canActivate: [CanActivateProductWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'order',
|
||||
loadChildren: () => import('@page/customer-order').then((m) => m.CustomerOrderModule),
|
||||
canActivate: [CanActivateCustomerOrdersGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/order',
|
||||
loadChildren: () => import('@page/customer-order').then((m) => m.CustomerOrderModule),
|
||||
canActivate: [CanActivateCustomerOrdersWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'customer',
|
||||
loadChildren: () => import('@page/customer').then((m) => m.CustomerModule),
|
||||
canActivate: [CanActivateCustomerGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/customer',
|
||||
loadChildren: () => import('@page/customer').then((m) => m.CustomerModule),
|
||||
canActivate: [CanActivateCustomerWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'cart',
|
||||
loadChildren: () => import('@page/checkout').then((m) => m.PageCheckoutModule),
|
||||
canActivate: [CanActivateCartGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/cart',
|
||||
loadChildren: () => import('@page/checkout').then((m) => m.PageCheckoutModule),
|
||||
canActivate: [CanActivateCartWithProcessIdGuard],
|
||||
},
|
||||
{
|
||||
path: 'pickup-shelf',
|
||||
canActivate: [ProcessIdGuard],
|
||||
// NOTE: This is a workaround for the canActivate guard not being called
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
path: ':processId/pickup-shelf',
|
||||
canActivate: [ActivateProcessIdGuard],
|
||||
loadChildren: () => import('@page/pickup-shelf').then((m) => m.PickupShelfOutModule),
|
||||
},
|
||||
{
|
||||
path: 'goods/out',
|
||||
loadChildren: () => import('@page/goods-out').then((m) => m.GoodsOutModule),
|
||||
canActivate: [CanActivateGoodsOutGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/goods/out',
|
||||
loadChildren: () => import('@page/goods-out').then((m) => m.GoodsOutModule),
|
||||
canActivate: [CanActivateGoodsOutWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{ path: '**', redirectTo: 'dashboard', pathMatch: 'full' },
|
||||
],
|
||||
resolve: { section: CustomerSectionResolver },
|
||||
},
|
||||
{
|
||||
path: 'filiale',
|
||||
component: MainComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'task-calendar',
|
||||
loadChildren: () => import('@page/task-calendar').then((m) => m.PageTaskCalendarModule),
|
||||
canActivate: [CanActivateTaskCalendarGuard],
|
||||
},
|
||||
{
|
||||
path: 'goods/in',
|
||||
loadChildren: () => import('@page/goods-in').then((m) => m.GoodsInModule),
|
||||
canActivate: [CanActivateGoodsInGuard],
|
||||
},
|
||||
{
|
||||
path: 'remission',
|
||||
loadChildren: () => import('@page/remission').then((m) => m.PageRemissionModule),
|
||||
canActivate: [CanActivateRemissionGuard],
|
||||
},
|
||||
{
|
||||
path: 'package-inspection',
|
||||
loadChildren: () => import('@page/package-inspection').then((m) => m.PackageInspectionModule),
|
||||
canActivate: [CanActivatePackageInspectionGuard],
|
||||
},
|
||||
{
|
||||
path: 'assortment',
|
||||
loadChildren: () => import('@page/assortment').then((m) => m.AssortmentModule),
|
||||
canActivate: [CanActivateAssortmentGuard],
|
||||
},
|
||||
{ path: '**', redirectTo: 'task-calendar', pathMatch: 'full' },
|
||||
],
|
||||
resolve: { section: BranchSectionResolver },
|
||||
},
|
||||
{ path: '**', redirectTo: 'kunde', pathMatch: 'full' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
27
apps/isa-app/src/app/guards/activate-process-id.guard.ts
Normal file
27
apps/isa-app/src/app/guards/activate-process-id.guard.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
||||
const application = inject(ApplicationService);
|
||||
|
||||
const processIdStr = route.params.processId;
|
||||
|
||||
if (!processIdStr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const processId = Number(processIdStr);
|
||||
|
||||
// Check if Process already exists
|
||||
const process = await application.getProcessById$(processId).pipe(take(1)).toPromise();
|
||||
|
||||
if (!process) {
|
||||
application.createCustomerProcess(processId);
|
||||
}
|
||||
|
||||
application.activateProcess(processId);
|
||||
|
||||
return true;
|
||||
};
|
||||
35
apps/isa-app/src/app/guards/process-id.guard.ts
Normal file
35
apps/isa-app/src/app/guards/process-id.guard.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
export const ProcessIdGuard: CanActivateFn = async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Promise<boolean | UrlTree> => {
|
||||
const application = inject(ApplicationService);
|
||||
const router = inject(Router);
|
||||
|
||||
const process = await application.getLastActivatedProcessWithSection$('customer').pipe(take(1)).toPromise();
|
||||
|
||||
const processId = process?.id ?? Date.now();
|
||||
|
||||
const originalUrl = state.url?.split('?')[0] ?? '';
|
||||
|
||||
let url: string = '';
|
||||
|
||||
if (originalUrl.startsWith('/kunde')) {
|
||||
url = originalUrl.replace('/kunde', `/kunde/${processId}`);
|
||||
} else {
|
||||
url = originalUrl.replace('/filiale', `/filiale/${processId}`);
|
||||
}
|
||||
|
||||
if (originalUrl === url) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return router.createUrlTree([url], {
|
||||
queryParams: route.queryParams,
|
||||
fragment: route.fragment,
|
||||
});
|
||||
};
|
||||
261
apps/page/pickup-shelf/src/lib/pickup-shelf-base.component.ts
Normal file
261
apps/page/pickup-shelf/src/lib/pickup-shelf-base.component.ts
Normal file
@@ -0,0 +1,261 @@
|
||||
import { DestroyRef, inject } from '@angular/core';
|
||||
import { PickupShelfStore } from './store';
|
||||
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, 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 { NavigationRoute } from '@shared/services';
|
||||
import { DBHOrderItemListItemDTO } from '@swagger/oms';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
/**
|
||||
* Enthält die gemeinsame Logik für die Suche und verbindet die Komponenten mit dem Store.
|
||||
*/
|
||||
export abstract class PickupShelfBaseComponent {
|
||||
protected destroyRef = inject(DestroyRef);
|
||||
|
||||
protected store = inject(PickupShelfStore);
|
||||
|
||||
protected router = inject(Router);
|
||||
|
||||
protected activatedRoute = inject(ActivatedRoute);
|
||||
|
||||
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) => {
|
||||
const queryParams = this.activatedRoute.snapshot.queryParams;
|
||||
const filterQueryParams = this.store.filter.getQueryParams();
|
||||
if (response.hits === 1) {
|
||||
const detailsPath = await this.getPathForDetail(response.result[0]);
|
||||
await this.router.navigate(detailsPath.path, { queryParams: { ...queryParams, ...filterQueryParams, ...detailsPath.queryParams } });
|
||||
} else if (response.hits > 1) {
|
||||
const listPath = await this.getPathFoList();
|
||||
await this.router.navigate(listPath.path, { queryParams: { ...queryParams, ...filterQueryParams, ...listPath.queryParams } });
|
||||
} else {
|
||||
// TODO: Fehlermeldung in Suchbux
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
this.runCheck();
|
||||
}
|
||||
|
||||
protected runCheck() {
|
||||
this._checkAndUpdateProcessIdInStore();
|
||||
this._checkAndUpdateQueryParamsInStore();
|
||||
this._checkAndUpdateBreadcrumb();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sucht die Breadcrumb anhand des Tags.
|
||||
* @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];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update die Main Breadcrumb.
|
||||
* @param breadcrumb Der Aktuelle Breadcrumb Tag
|
||||
*/
|
||||
@logAsync
|
||||
private async _checkAndUpdateMainBreadcrumb(breadcrumb: string) {
|
||||
let mainBreadcrumb: Breadcrumb = await this._getBreadcrumbByTag('main');
|
||||
|
||||
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 getNameForMainBreadcrumb(): Promise<string>;
|
||||
|
||||
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', '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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract getPathForDetail(item: DBHOrderItemListItemDTO): Promise<NavigationRoute>;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export abstract class PickupShelfDetailsBaseComponent {
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Details</h1>
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { PickupShelfDetailsBaseComponent } from '../../pickup-shelf-details-base.component';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-in-details',
|
||||
templateUrl: 'pickup-shelf-in-details.component.html',
|
||||
styleUrls: ['pickup-shelf-in-details.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'page-pickup-shelf-in-details' },
|
||||
standalone: true,
|
||||
imports: [],
|
||||
})
|
||||
export class PickupShelfInDetailsComponent extends PickupShelfDetailsBaseComponent {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<shared-breadcrumb></shared-breadcrumb>
|
||||
<shared-splitscreen></shared-splitscreen>
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { BreadcrumbModule } from '@shared/components/breadcrumb';
|
||||
import { SharedSplitscreenComponent } from '@shared/components/splitscreen';
|
||||
import { PickupShelfStore } from '../store';
|
||||
import { provideComponentStore } from '@ngrx/component-store';
|
||||
import { PickupShelfIOService, PickupShelfInService } from '@domain/pickup-shelf';
|
||||
import { PickupShelfBaseComponent } from '../pickup-shelf-base.component';
|
||||
import { NavigationRoute, PickupShelfInNavigationService } from '@shared/services';
|
||||
import { DBHOrderItemListItemDTO } from '@swagger/oms';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-in',
|
||||
templateUrl: 'pickup-shelf-in.component.html',
|
||||
styleUrls: ['pickup-shelf-in.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'page-pickup-shelf-in' },
|
||||
standalone: true,
|
||||
imports: [BreadcrumbModule, SharedSplitscreenComponent],
|
||||
providers: [provideComponentStore(PickupShelfStore), { provide: PickupShelfIOService, useClass: PickupShelfInService }],
|
||||
})
|
||||
export class PickupShelfInComponent extends PickupShelfBaseComponent {
|
||||
private _pickupShelfInNavigationService = inject(PickupShelfInNavigationService);
|
||||
|
||||
async getPathForMain(): Promise<NavigationRoute> {
|
||||
return this._pickupShelfInNavigationService.defaultRoute();
|
||||
}
|
||||
async getNameForMainBreadcrumb(): Promise<string> {
|
||||
return 'Wareneingang';
|
||||
}
|
||||
|
||||
async getNameForListBreadcrumb(): Promise<string> {
|
||||
return 'Liste';
|
||||
}
|
||||
|
||||
async getPathFoList(): Promise<NavigationRoute> {
|
||||
return this._pickupShelfInNavigationService.listRoute();
|
||||
}
|
||||
|
||||
async getNameForFilterBreadcrumb(): Promise<string> {
|
||||
return 'Filter';
|
||||
}
|
||||
async getPathForFilter(): Promise<NavigationRoute> {
|
||||
return this._pickupShelfInNavigationService.filterRoute();
|
||||
}
|
||||
|
||||
async getPathForDetail(item: DBHOrderItemListItemDTO): Promise<NavigationRoute> {
|
||||
return this._pickupShelfInNavigationService.detailRoute({ item });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { routes } from './routes';
|
||||
import { provideComponentStore } from '@ngrx/component-store';
|
||||
import { PickupShelfStore } from '../store/pickup-shelf.store';
|
||||
import { PickupShelfIOService, PickupShelfInService } from '@domain/pickup-shelf';
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
})
|
||||
export class PickupShelfInModule {}
|
||||
19
apps/page/pickup-shelf/src/lib/pickup-shelf-in/routes.ts
Normal file
19
apps/page/pickup-shelf/src/lib/pickup-shelf-in/routes.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { PickupShelfInComponent } from './pickup-shelf-in.component';
|
||||
import { PickupShelfFilterComponent } from '../shared/pickup-shelf-filter/pickup-shelf-filter.component';
|
||||
import { PickupShelfInDetailsComponent } from './pickup-shelf-in-details/pickup-shelf-in-details.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PickupShelfInComponent,
|
||||
children: [
|
||||
{ path: '', data: { breadcrumb: 'main' } },
|
||||
{ path: 'list', data: { breadcrumb: 'list' } },
|
||||
{ path: 'list/filter', component: PickupShelfFilterComponent, data: { breadcrumb: 'filter' } },
|
||||
{ path: 'order/:orderId/:orderItemId', component: PickupShelfInDetailsComponent, data: { breadcrumb: 'details' } },
|
||||
// { path: 'main', outlet: 'side' },
|
||||
// { path: 'list', outlet: 'side' },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Details</h1>
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { PickupShelfDetailsBaseComponent } from '../../pickup-shelf-details-base.component';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-out-details',
|
||||
templateUrl: 'pickup-shelf-out-details.component.html',
|
||||
styleUrls: ['pickup-shelf-out-details.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'page-pickup-shelf-out-details' },
|
||||
standalone: true,
|
||||
imports: [],
|
||||
})
|
||||
export class PickupShelfOutDetailsComponent extends PickupShelfDetailsBaseComponent {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<div>Hits {{ hits$ | async }}</div>
|
||||
<div *ngFor="let item of list$ | async">
|
||||
{{ item.orderNumber }}
|
||||
</div>
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { PickupShelfStore } from '../../store';
|
||||
import { AsyncPipe, NgFor } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pcikup-shelf-out-list',
|
||||
templateUrl: 'pickup-shelf-out-list.component.html',
|
||||
styleUrls: ['pickup-shelf-out-list.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'page-pcikup-shelf-out-list' },
|
||||
standalone: true,
|
||||
imports: [AsyncPipe, NgFor],
|
||||
})
|
||||
export class PickupShelfOutListComponent {
|
||||
store = inject(PickupShelfStore);
|
||||
|
||||
list$ = this.store.list$;
|
||||
|
||||
hits$ = this.store.listHits$;
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<page-pcikup-shelf-filter></page-pcikup-shelf-filter>
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { PickupShelfFilterComponent } from '../../shared/pickup-shelf-filter/pickup-shelf-filter.component';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-out-main',
|
||||
templateUrl: 'pickup-shelf-out-main.component.html',
|
||||
styleUrls: ['pickup-shelf-out-main.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'page-pickup-shelf-out-main' },
|
||||
standalone: true,
|
||||
imports: [PickupShelfFilterComponent],
|
||||
})
|
||||
export class PickupShelfOutMainComponent {
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<shared-breadcrumb [key]="store.processId$ | async" [tags]="['pickup-shelf']"></shared-breadcrumb>
|
||||
<shared-splitscreen></shared-splitscreen>
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { BreadcrumbModule } from '@shared/components/breadcrumb';
|
||||
import { SharedSplitscreenComponent } from '@shared/components/splitscreen';
|
||||
import { PickupShelfStore } from '../store';
|
||||
import { provideComponentStore } from '@ngrx/component-store';
|
||||
import { PickupShelfIOService, PickupShelfOutService } from '@domain/pickup-shelf';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pickup-shelf-out',
|
||||
templateUrl: 'pickup-shelf-out.component.html',
|
||||
styleUrls: ['pickup-shelf-out.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'page-pickup-shelf-out' },
|
||||
standalone: true,
|
||||
imports: [BreadcrumbModule, SharedSplitscreenComponent, AsyncPipe],
|
||||
providers: [provideComponentStore(PickupShelfStore), { provide: PickupShelfIOService, useClass: PickupShelfOutService }],
|
||||
})
|
||||
export class PickupShelfOutComponent extends PickupShelfBaseComponent {
|
||||
private _pickupShelfOutNavigationService = inject(PickupShelfOutNavigationService);
|
||||
|
||||
@logAsync
|
||||
async getPathForMain(): Promise<NavigationRoute> {
|
||||
return this._pickupShelfOutNavigationService.defaultRoute({ processId: this.store.processId });
|
||||
}
|
||||
|
||||
@logAsync
|
||||
async getNameForMainBreadcrumb(): Promise<string> {
|
||||
return 'Warenausgabe';
|
||||
}
|
||||
|
||||
@logAsync
|
||||
async getNameForListBreadcrumb(): Promise<string> {
|
||||
return 'Liste';
|
||||
}
|
||||
|
||||
@logAsync
|
||||
async getPathFoList(): Promise<NavigationRoute> {
|
||||
return this._pickupShelfOutNavigationService.listRoute({ processId: this.store.processId });
|
||||
}
|
||||
|
||||
@logAsync
|
||||
async getNameForFilterBreadcrumb(): Promise<string> {
|
||||
return 'Filter';
|
||||
}
|
||||
|
||||
@logAsync
|
||||
async getPathForFilter(): Promise<NavigationRoute> {
|
||||
return this._pickupShelfOutNavigationService.filterRoute({ processId: this.store.processId });
|
||||
}
|
||||
|
||||
@logAsync
|
||||
async getPathForDetail(item: DBHOrderItemListItemDTO): Promise<NavigationRoute> {
|
||||
return this._pickupShelfOutNavigationService.detailRoute({ processId: this.store.processId, item });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { routes } from './routes';
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
})
|
||||
export class PickupShelfOutModule {}
|
||||
23
apps/page/pickup-shelf/src/lib/pickup-shelf-out/routes.ts
Normal file
23
apps/page/pickup-shelf/src/lib/pickup-shelf-out/routes.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { PickupShelfOutComponent } from './pickup-shelf-out.component';
|
||||
import { PickupShelfOutMainComponent } from './pickup-shelf-out-main/pickup-shelf-out-main.component';
|
||||
|
||||
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';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PickupShelfOutComponent,
|
||||
children: [
|
||||
{ path: '', component: PickupShelfOutMainComponent, data: { breadcrumb: 'main' } },
|
||||
{ path: 'list', component: PickupShelfOutListComponent, data: { breadcrumb: 'list' } },
|
||||
{ path: 'list/filter', component: PickupShelfFilterComponent, data: { breadcrumb: 'filter' } },
|
||||
{ path: 'order/:orderId/:processingStatus', component: PickupShelfOutDetailsComponent, data: { breadcrumb: 'details' } },
|
||||
{ path: 'compartment/:compartment', component: PickupShelfOutDetailsComponent, data: { breadcrumb: 'details' } },
|
||||
// { path: 'main', outlet: 'side' },
|
||||
// { path: 'list', outlet: 'side' },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,7 @@
|
||||
:host {
|
||||
@apply block bg-white p-4;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-2xl font-bold text-center pb-6;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="text-right">
|
||||
<button type="button" (click)="clearFilter()">Alle Filter entfernen</button>
|
||||
</div>
|
||||
<h1>Filter</h1>
|
||||
<div *ngIf="filter$ | async; let filter">
|
||||
<shared-filter [filter]="filter" (search)="applyFilter(filter)"></shared-filter>
|
||||
<button type="button" (click)="resetFilter()">Filter zurücksetzen</button>
|
||||
<button type="button" (click)="applyFilter(filter)">Filter anwenden</button>
|
||||
</div>
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
|
||||
import { Filter, FilterModule } from '@shared/components/filter';
|
||||
import { PickupShelfStore } from '../../store';
|
||||
import { AsyncPipe, NgIf } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'page-pcikup-shelf-filter',
|
||||
templateUrl: 'pickup-shelf-filter.component.html',
|
||||
styleUrls: ['pickup-shelf-filter.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'page-pcikup-shelf-filter' },
|
||||
standalone: true,
|
||||
imports: [FilterModule, AsyncPipe, NgIf],
|
||||
})
|
||||
export class PickupShelfFilterComponent {
|
||||
store = inject(PickupShelfStore);
|
||||
|
||||
filter$ = this.store.filter$;
|
||||
|
||||
constructor() {}
|
||||
|
||||
resetFilter() {
|
||||
this.store.setQueryParams(undefined);
|
||||
}
|
||||
|
||||
applyFilter(filter: Filter) {
|
||||
this.store.setQueryParams(filter.getQueryParams());
|
||||
this.store.fetchList();
|
||||
}
|
||||
|
||||
clearFilter() {
|
||||
this.store.setQueryParams({});
|
||||
}
|
||||
}
|
||||
1
apps/page/pickup-shelf/src/lib/store/index.ts
Normal file
1
apps/page/pickup-shelf/src/lib/store/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './pickup-shelf.store';
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Filter } from '@shared/components/filter';
|
||||
import { PickupShelfState } from './pickup-shelf.state';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
export function selectProcessId(state: PickupShelfState) {
|
||||
return state.processId;
|
||||
}
|
||||
|
||||
export function selectFetchingQuerySettings(state: PickupShelfState) {
|
||||
return state.fetchingQuerySettings ?? false;
|
||||
}
|
||||
|
||||
export function selectQuerySettings(state: PickupShelfState) {
|
||||
return state.querySettings;
|
||||
}
|
||||
|
||||
export function selectQueryParams(state: PickupShelfState) {
|
||||
return state.queryParams;
|
||||
}
|
||||
|
||||
export function selectDefaultFilter(state: PickupShelfState) {
|
||||
const querySettings = selectQuerySettings(state);
|
||||
|
||||
return querySettings ? Filter.create(querySettings) : undefined;
|
||||
}
|
||||
|
||||
export function selectFilter(state: PickupShelfState) {
|
||||
const queryParams = selectQueryParams(state);
|
||||
|
||||
const defaultFilter = selectDefaultFilter(state);
|
||||
|
||||
if (!defaultFilter) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const filter = Filter.create(defaultFilter);
|
||||
|
||||
// Wenn queryParams undefined ist, dann wird der Filter nicht gesetzt
|
||||
if (queryParams === undefined) {
|
||||
return filter;
|
||||
}
|
||||
|
||||
// Wenn queryParams ein leeres Objekt ist, dann wird der Filter gesetzt, aber ohne Werte (leerer Filter)
|
||||
if (isEmpty(queryParams)) {
|
||||
filter.unselectAllFilterOptions();
|
||||
return filter;
|
||||
}
|
||||
|
||||
// Wenn queryParams ein Objekt mit Werten ist, dann wird der Filter gesetzt
|
||||
filter.fromQueryParams(queryParams);
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
export function selectFetchingList(state: PickupShelfState) {
|
||||
return state.fetchingList ?? false;
|
||||
}
|
||||
|
||||
export function selectList(state: PickupShelfState) {
|
||||
return state.list ?? [];
|
||||
}
|
||||
|
||||
export function selectListHits(state: PickupShelfState) {
|
||||
return state.listHits ?? 0;
|
||||
}
|
||||
14
apps/page/pickup-shelf/src/lib/store/pickup-shelf.state.ts
Normal file
14
apps/page/pickup-shelf/src/lib/store/pickup-shelf.state.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { DBHOrderItemListItemDTO, QuerySettingsDTO } from '@swagger/oms';
|
||||
|
||||
export interface PickupShelfState {
|
||||
processId?: number;
|
||||
|
||||
fetchingQuerySettings?: boolean;
|
||||
querySettings?: QuerySettingsDTO;
|
||||
|
||||
queryParams?: Record<string, string>;
|
||||
|
||||
fetchingList?: boolean;
|
||||
list?: DBHOrderItemListItemDTO[];
|
||||
listHits?: number;
|
||||
}
|
||||
160
apps/page/pickup-shelf/src/lib/store/pickup-shelf.store.ts
Normal file
160
apps/page/pickup-shelf/src/lib/store/pickup-shelf.store.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import { ComponentStore, tapResponse, OnStoreInit } from '@ngrx/component-store';
|
||||
import { PickupShelfState } from './pickup-shelf.state';
|
||||
import { PickupShelfIOService } from '@domain/pickup-shelf';
|
||||
import { delayWhen, switchMap, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { ListResponseArgsOfDBHOrderItemListItemDTO, ResponseArgsOfQuerySettingsDTO } from '@swagger/oms';
|
||||
import { DestroyRef, Injectable, inject } from '@angular/core';
|
||||
import { ToasterService } from '@shared/shell';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
|
||||
import * as Selectors from './pickup-shelf.selectors';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class PickupShelfStore extends ComponentStore<PickupShelfState> implements OnStoreInit {
|
||||
private _destronyRef = inject(DestroyRef);
|
||||
|
||||
private _cancelListRequests = new Subject<void>();
|
||||
|
||||
private _pickupShelfIOService = inject(PickupShelfIOService);
|
||||
|
||||
private _toasterService = inject(ToasterService);
|
||||
|
||||
private _modalService = inject(UiModalService);
|
||||
|
||||
readonly processId$ = this.select(Selectors.selectProcessId);
|
||||
|
||||
private _fetchListResponse = new Subject<ListResponseArgsOfDBHOrderItemListItemDTO>();
|
||||
|
||||
readonly fetchListResponse$ = this._fetchListResponse.asObservable();
|
||||
|
||||
get processId() {
|
||||
return this.get(Selectors.selectProcessId);
|
||||
}
|
||||
|
||||
readonly filter$ = this.select(Selectors.selectFilter);
|
||||
|
||||
get filter() {
|
||||
return this.get(Selectors.selectFilter);
|
||||
}
|
||||
|
||||
readonly list$ = this.select(Selectors.selectList);
|
||||
|
||||
get list() {
|
||||
return this.get(Selectors.selectList);
|
||||
}
|
||||
|
||||
readonly listHits$ = this.select(Selectors.selectListHits);
|
||||
|
||||
get listHits() {
|
||||
return this.get(Selectors.selectListHits);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
// Nicht entfernen sonst wird der Store nicht initialisiert
|
||||
super({});
|
||||
|
||||
this._destronyRef.onDestroy(() => {
|
||||
this.cancelListRequests();
|
||||
this._fetchListResponse.complete();
|
||||
});
|
||||
}
|
||||
|
||||
setProcessId(processId: number) {
|
||||
if (this.processId === processId) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.cancelListRequests();
|
||||
this.patchState({ processId: processId, fetchingList: false, list: [], listHits: 0, queryParams: {} });
|
||||
}
|
||||
|
||||
setQueryParams(queryParams: Record<string, string> | undefined) {
|
||||
this.patchState({ queryParams });
|
||||
}
|
||||
|
||||
cancelListRequests() {
|
||||
this._cancelListRequests.next();
|
||||
}
|
||||
|
||||
ngrxOnStoreInit = () => {
|
||||
this.fetchQuerySettings();
|
||||
};
|
||||
|
||||
fetchQuerySettings = this.effect((trigger$) =>
|
||||
trigger$.pipe(
|
||||
tap(() => this.patchState({ fetchingQuerySettings: true })),
|
||||
switchMap(() =>
|
||||
this._pickupShelfIOService.getQuerySettings().pipe(tapResponse(this.fetchQuerySettingsDone, this.fetchQuerySettingsError))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
private fetchQuerySettingsDone = (resp: ResponseArgsOfQuerySettingsDTO) => {
|
||||
this.patchState({ fetchingQuerySettings: false, querySettings: resp.result });
|
||||
};
|
||||
|
||||
private fetchQuerySettingsError = (err: any) => {
|
||||
this._modalService.error('Fehler beim Laden der Filtereinstellungen', err);
|
||||
this.patchState({ fetchingQuerySettings: false });
|
||||
};
|
||||
|
||||
delayWhenFilterIsNotReady = delayWhen(() => this.filter$.pipe(tap((filter) => !!filter)));
|
||||
|
||||
fetchList = this.effect((trigger$) =>
|
||||
trigger$.pipe(
|
||||
this.delayWhenFilterIsNotReady,
|
||||
tap(this.beforeFetchList),
|
||||
withLatestFrom(this.filter$),
|
||||
switchMap(([_, filter]) =>
|
||||
this._pickupShelfIOService
|
||||
.search(filter.getQueryToken())
|
||||
.pipe(takeUntil(this._cancelListRequests), tapResponse(this.fetchListDone, this.fetchListError))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
private beforeFetchList = () => {
|
||||
this.cancelListRequests();
|
||||
this.patchState({ fetchingList: true, list: [], listHits: 0 });
|
||||
};
|
||||
|
||||
private fetchListDone = (resp: ListResponseArgsOfDBHOrderItemListItemDTO) => {
|
||||
this.patchState({ fetchingList: false, list: resp.result, listHits: resp.hits });
|
||||
this._fetchListResponse.next(resp);
|
||||
};
|
||||
|
||||
private fetchListError = (err: any) => {
|
||||
this._modalService.error('Fehler beim Laden der Liste', err);
|
||||
this.patchState({ fetchingList: false });
|
||||
};
|
||||
|
||||
fetchMoreList = this.effect((trigger$) =>
|
||||
trigger$.pipe(
|
||||
// TODO: Skip if fethcing is already in progress
|
||||
tap(this.beforeFetchMoreList),
|
||||
withLatestFrom(this.filter$, this.listHits$),
|
||||
switchMap(([_, filter, listHits]) => {
|
||||
const queryToken = filter.getQueryToken();
|
||||
queryToken.skip = listHits;
|
||||
return this._pickupShelfIOService
|
||||
.search(queryToken)
|
||||
.pipe(takeUntil(this._cancelListRequests), tapResponse(this.fetchMoreListDone, this.fetchMoreListError));
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
private beforeFetchMoreList = () => {
|
||||
this.cancelListRequests();
|
||||
this.patchState({ fetchingList: true });
|
||||
};
|
||||
|
||||
private fetchMoreListDone = (resp: ListResponseArgsOfDBHOrderItemListItemDTO) => {
|
||||
this.patchState({ fetchingList: false, list: [...this.list, ...resp.result], listHits: resp.hits });
|
||||
};
|
||||
|
||||
private fetchMoreListError = (err: any) => {
|
||||
this._modalService.error('Fehler beim Laden der Liste', err);
|
||||
this.patchState({ fetchingList: false });
|
||||
};
|
||||
}
|
||||
2
apps/page/pickup-shelf/src/public-api.ts
Normal file
2
apps/page/pickup-shelf/src/public-api.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './lib/pickup-shelf-out/pickup-shelf-out.module';
|
||||
export * from './lib/pickup-shelf-in/pickup-shelf-in.module';
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { NavigationRoute } from './navigation-route';
|
||||
import { Router } from '@angular/router';
|
||||
import { Config } from '@core/config';
|
||||
import { DBHOrderItemListItemDTO } from '@swagger/oms';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PickupShelfInNavigationService {
|
||||
private readonly _router = inject(Router);
|
||||
|
||||
private readonly _config = inject(Config);
|
||||
|
||||
defaultRoute(): NavigationRoute {
|
||||
const path = ['/filiale', 'pickup-shelf'].filter((v) => !!v);
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
|
||||
listRoute(): NavigationRoute {
|
||||
const path = ['/filiale', 'pickup-shelf', 'list'].filter((v) => !!v);
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
|
||||
filterRoute(): NavigationRoute {
|
||||
const path = ['/filiale', 'pickup-shelf', 'list', 'filter'].filter((v) => !!v);
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
|
||||
detailRoute({ item }: { item: DBHOrderItemListItemDTO }): NavigationRoute {
|
||||
const path = ['/filiale', 'pickup-shelf', 'order', item.orderId, item.orderItemId].filter((v) => !!v);
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { NavigationRoute } from './navigation-route';
|
||||
import { Router } from '@angular/router';
|
||||
import { DBHOrderItemListItemDTO } from '@swagger/oms';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PickupShelfOutNavigationService {
|
||||
private readonly _router = inject(Router);
|
||||
|
||||
defaultRoute({ processId }: { processId?: number }): NavigationRoute {
|
||||
const path = ['/kunde', processId ? processId : undefined, 'pickup-shelf'].filter((v) => !!v);
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
|
||||
listRoute({ processId }: { processId?: number }): NavigationRoute {
|
||||
const path = ['/kunde', processId ? processId : undefined, 'pickup-shelf', 'list'].filter((v) => !!v);
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
|
||||
filterRoute({ processId }: { processId?: number }): NavigationRoute {
|
||||
const path = ['/kunde', processId ? processId : undefined, 'pickup-shelf', 'list', 'filter'].filter((v) => !!v);
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
|
||||
detailRoute({ processId, item }: { processId?: number; item: DBHOrderItemListItemDTO }): NavigationRoute {
|
||||
let path: any[];
|
||||
|
||||
if (item.compartmentCode) {
|
||||
path = ['/kunde', processId ? processId : undefined, 'pickup-shelf', 'compartment', item.compartmentCode].filter((v) => !!v);
|
||||
} else {
|
||||
path = ['/kunde', processId ? processId : undefined, 'pickup-shelf', 'order', item.orderId, item.processingStatus].filter((v) => !!v);
|
||||
}
|
||||
|
||||
const queryParams = {};
|
||||
|
||||
const urlTree = this._router.createUrlTree(path, { queryParams });
|
||||
|
||||
return {
|
||||
path,
|
||||
queryParams,
|
||||
urlTree,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,6 @@ export * from './lib/customer-create.navigation';
|
||||
export * from './lib/customer-search.navigation';
|
||||
export * from './lib/navigation-route';
|
||||
export * from './lib/navigation.service';
|
||||
export * from './lib/pickup-shelf-out-navigation.service';
|
||||
export * from './lib/pickup-shelf-in-navigation.service';
|
||||
export * from './lib/defs';
|
||||
|
||||
@@ -71,23 +71,7 @@ export class ShellProcessBarComponent implements OnInit {
|
||||
static REGEX_PROCESS_NAME = /^Vorgang \d+$/;
|
||||
|
||||
async createCartProcess() {
|
||||
const processes = await this._app.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
const processIds = processes.filter((x) => ShellProcessBarComponent.REGEX_PROCESS_NAME.test(x.name)).map((x) => +x.name.split(' ')[1]);
|
||||
|
||||
const maxId = processIds.length > 0 ? Math.max(...processIds) : 0;
|
||||
|
||||
const process: ApplicationProcess = {
|
||||
id: Date.now(),
|
||||
type: 'cart',
|
||||
name: `Vorgang ${maxId + 1}`,
|
||||
section: 'customer',
|
||||
closeable: true,
|
||||
};
|
||||
|
||||
this._app.createProcess(process);
|
||||
|
||||
return process;
|
||||
return this._app.createCustomerProcess();
|
||||
}
|
||||
|
||||
async navigateTo(target: string, process: ApplicationProcess) {
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
"@core/*": [
|
||||
"apps/core/*/src/public-api.ts"
|
||||
],
|
||||
"@domain/*": [
|
||||
"apps/domain/*/src/public-api.ts"
|
||||
],
|
||||
"@domain/availability": [
|
||||
"apps/domain/availability/src/public-api.ts"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user