mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merge tag 'post-2.1-hotfix' into develop (conflicts resolved)
This commit is contained in:
@@ -66,24 +66,15 @@ export class ReOrderActionHandler extends ActionHandler<OrderItemsContext> {
|
||||
}
|
||||
|
||||
createToast(comment?: string) {
|
||||
let text: string = '';
|
||||
|
||||
switch (comment) {
|
||||
case 'Artikel unverkäuflich, (und physisch in der Filiale vorhanden)':
|
||||
text = 'Der Beschädigte Artikel wurde auf die Remi-Liste gesetzt.';
|
||||
break;
|
||||
case 'Falscher Titel geliefert (richtiges Etikett)':
|
||||
text = 'Die Falschlieferung wurde auf die Remi-Liste gesetzt.';
|
||||
break;
|
||||
default:
|
||||
text = '';
|
||||
break;
|
||||
this._toastService.create({
|
||||
title: 'Artikel wurde nachbestellt',
|
||||
});
|
||||
}
|
||||
|
||||
this._toastService.create({
|
||||
title: 'Artikel wurde nachbestellt',
|
||||
text,
|
||||
});
|
||||
}
|
||||
|
||||
async reorder(orderItem: OrderItemListItemDTO, availability: AvailabilityDTO2, comment: string) {
|
||||
|
||||
@@ -32,18 +32,18 @@ export class DomainGoodsService {
|
||||
});
|
||||
}
|
||||
|
||||
getWarenausgabeItemByOrderNumber(orderNumber: string) {
|
||||
getWarenausgabeItemByOrderNumber(orderNumber: string, archive: boolean) {
|
||||
return this.abholfachService.AbholfachWarenausgabe({
|
||||
filter: { all_branches: 'true', archive: 'true' },
|
||||
filter: { all_branches: 'true', archive: `${archive}` },
|
||||
input: {
|
||||
qs: orderNumber,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getWarenausgabeItemByCompartment(compartmentCode: string) {
|
||||
getWarenausgabeItemByCompartment(compartmentCode: string, archive: boolean) {
|
||||
return this.abholfachService.AbholfachWarenausgabe({
|
||||
filter: { all_branches: 'true', archive: 'true' },
|
||||
filter: { all_branches: 'true', archive: `${archive}` },
|
||||
input: {
|
||||
qs: compartmentCode,
|
||||
},
|
||||
|
||||
@@ -6,9 +6,9 @@ import { ApplicationService } from '@core/application';
|
||||
import { of } from 'rxjs';
|
||||
import { Renderer2 } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ServiceWorkerModule, SwUpdate } from '@angular/service-worker';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { NotificationsHub } from '@hub/notifications';
|
||||
import { discardPeriodicTasks, fakeAsync, flush, tick } from '@angular/core/testing';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
let spectator: Spectator<AppComponent>;
|
||||
@@ -21,7 +21,7 @@ describe('AppComponent', () => {
|
||||
component: AppComponent,
|
||||
imports: [CommonModule, RouterTestingModule],
|
||||
providers: [],
|
||||
mocks: [Config, SwUpdate],
|
||||
mocks: [Config, SwUpdate, UserStateService],
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -10,6 +10,8 @@ import { interval, Observable, Subscription } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { Platform } from '@angular/cdk/platform';
|
||||
import { Router } from '@angular/router';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { IsaLogProvider } from './providers';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -40,16 +42,17 @@ export class AppComponent implements OnInit {
|
||||
private readonly _swUpdate: SwUpdate,
|
||||
private readonly _notifications: NotificationsHub,
|
||||
private readonly _platform: Platform,
|
||||
private router: Router
|
||||
private router: Router,
|
||||
private infoService: UserStateService
|
||||
) {
|
||||
this.updateClient();
|
||||
IsaLogProvider.InfoService = infoService;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.setTitle();
|
||||
this.logVersion();
|
||||
this.determinePlatform();
|
||||
|
||||
this._appService.getSection$().subscribe(this.sectionChangeHandler.bind(this));
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import { ScanAdapterModule, ScanAdapterService, ScanditScanAdapterModule } from
|
||||
import { RootStateService } from './store/root-state.service';
|
||||
import * as Commands from './commands';
|
||||
import { UiIconModule } from '@ui/icon';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
|
||||
registerLocaleData(localeDe, localeDeExtra);
|
||||
registerLocaleData(localeDe, 'de', localeDeExtra);
|
||||
|
||||
@@ -4,10 +4,12 @@ import { Observable, throwError } from 'rxjs';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { catchError, mergeMap, tap } from 'rxjs/operators';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { IsaLogProvider } from '../providers';
|
||||
import { LogLevel } from '@core/logger';
|
||||
|
||||
@Injectable()
|
||||
export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
constructor(private _modal: UiModalService, private _auth: AuthService) {}
|
||||
constructor(private _modal: UiModalService, private _auth: AuthService, private _isaLogProvider: IsaLogProvider) {}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(req).pipe(catchError((error: HttpErrorResponse, caught: any) => this.handleError(error)));
|
||||
@@ -37,6 +39,8 @@ export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
);
|
||||
}
|
||||
|
||||
this._isaLogProvider.log(LogLevel.ERROR, 'Http Error', error);
|
||||
|
||||
return throwError(error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@ import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { ErrorHandler, Injectable } from '@angular/core';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { DialogModel, UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
|
||||
import { IsaLogProvider } from './isa.log-provider';
|
||||
import { LogLevel } from '@core/logger';
|
||||
|
||||
@Injectable()
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class IsaErrorHandler implements ErrorHandler {
|
||||
constructor(private _modal: UiModalService, private _authService: AuthService) {}
|
||||
constructor(private _modal: UiModalService, private _authService: AuthService, private _isaLogProvider: IsaLogProvider) {}
|
||||
|
||||
async handleError(error: any): Promise<void> {
|
||||
console.error(error);
|
||||
@@ -33,6 +35,8 @@ export class IsaErrorHandler implements ErrorHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isaLogProvider.log(LogLevel.ERROR, 'Client Error', error);
|
||||
|
||||
this._modal.open({
|
||||
content: UiErrorModalComponent,
|
||||
title:
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { LogLevel, LogProvider } from '@core/logger';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Injectable()
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class IsaLogProvider implements LogProvider {
|
||||
constructor(private readonly _infoService: UserStateService) {}
|
||||
static InfoService: UserStateService | undefined;
|
||||
|
||||
log(logLevel: LogLevel, message: string, ...optionalParams: any[]): void {
|
||||
constructor() {}
|
||||
|
||||
log(logLevel: LogLevel, message: string, error: Error, ...optionalParams: any[]): void {
|
||||
if (!environment.production && (logLevel === LogLevel.WARN || logLevel === LogLevel.ERROR)) {
|
||||
this._infoService
|
||||
.UserStateSaveLog({
|
||||
logType: logLevel,
|
||||
message: message,
|
||||
content: JSON.stringify(optionalParams),
|
||||
})
|
||||
IsaLogProvider.InfoService?.UserStateSaveLog({
|
||||
logType: logLevel,
|
||||
message: message,
|
||||
content: JSON.stringify({
|
||||
error: error?.name,
|
||||
message: error?.message,
|
||||
stack: error?.stack,
|
||||
data: optionalParams,
|
||||
}),
|
||||
})
|
||||
.toPromise()
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ export class GoodsInReservationSelectablePipe implements PipeTransform {
|
||||
if (selectedItems.length > 0) {
|
||||
const firstSelectedItem = selectedItems[0];
|
||||
const selectedLabel = firstSelectedItem.actions.find((action) => selectionRules(action)).label;
|
||||
return item?.actions?.some((action) => selectionRules(action) && action.label === selectedLabel);
|
||||
return item?.actions?.some(
|
||||
(action) => selectionRules(action) && action.label === selectedLabel && item?.features?.paid === firstSelectedItem?.features?.paid
|
||||
);
|
||||
} else {
|
||||
return item?.actions?.some((action) => selectionRules(action));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export interface GoodsOutDetailsComponentState {
|
||||
compartmentCode?: string;
|
||||
items?: OrderItemListItemDTO[];
|
||||
orderId?: number;
|
||||
archive?: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@@ -33,6 +34,11 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
|
||||
processingStatus$ = this.select((s) => s.processingStatus);
|
||||
|
||||
archive$ = this.select((s) => s.archive);
|
||||
get archive() {
|
||||
return this.get((s) => s.archive);
|
||||
}
|
||||
|
||||
items$ = this.select((s) => s.items ?? []);
|
||||
|
||||
orderId$ = this.select((s) => s.orderId);
|
||||
@@ -71,7 +77,8 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
ngOnInit() {
|
||||
this._activatedRoute.queryParams.pipe(takeUntil(this._onDestroy$)).subscribe((params) => {
|
||||
const buyerNumber: string = decodeURIComponent(params.buyerNumber ?? '');
|
||||
this.patchState({ buyerNumber });
|
||||
const archive = params?.archive || false;
|
||||
this.patchState({ buyerNumber, archive });
|
||||
});
|
||||
|
||||
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe(async (params) => {
|
||||
@@ -100,6 +107,7 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
path: this.getDetailsPath(item),
|
||||
params: {
|
||||
buyerNumber: item.buyerNumber,
|
||||
archive: this.archive,
|
||||
},
|
||||
section: 'customer',
|
||||
tags: ['goods-out', 'details', item?.compartmentCode || item?.orderNumber],
|
||||
@@ -131,13 +139,13 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
$.pipe(
|
||||
tap(() => this.patchState({ fetching: false })),
|
||||
debounceTime(500),
|
||||
withLatestFrom(this.orderNumber$, this.compartmentCode$),
|
||||
switchMap(([_, orderNumber, compartmentCode]) => {
|
||||
withLatestFrom(this.orderNumber$, this.compartmentCode$, this.archive$),
|
||||
switchMap(([_, orderNumber, compartmentCode, archive]) => {
|
||||
let request$: Observable<ListResponseArgsOfOrderItemListItemDTO>;
|
||||
if (compartmentCode) {
|
||||
request$ = this._domainGoodsInService.getWarenausgabeItemByCompartment(compartmentCode);
|
||||
request$ = this._domainGoodsInService.getWarenausgabeItemByCompartment(compartmentCode, archive);
|
||||
} else {
|
||||
request$ = this._domainGoodsInService.getWarenausgabeItemByOrderNumber(orderNumber);
|
||||
request$ = this._domainGoodsInService.getWarenausgabeItemByOrderNumber(orderNumber, archive);
|
||||
}
|
||||
|
||||
return combineLatest([request$, this.processingStatus$, this.buyerNumber$]).pipe(
|
||||
@@ -179,11 +187,15 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
}
|
||||
|
||||
navigateToEditPage(orderItem: OrderItemListItemDTO) {
|
||||
this._router.navigate([this.getEditPath(orderItem)], { queryParams: { buyerNumber: orderItem.buyerNumber } });
|
||||
this._router.navigate([this.getEditPath(orderItem)], {
|
||||
queryParams: { buyerNumber: orderItem.buyerNumber, archive: this.archive },
|
||||
});
|
||||
}
|
||||
|
||||
navigateToDetailsPage(item: OrderItemListItemDTO) {
|
||||
this._router.navigate([this.getDetailsPath(item)], { queryParams: { buyerNumber: item.buyerNumber } });
|
||||
this._router.navigate([this.getDetailsPath(item)], {
|
||||
queryParams: { buyerNumber: item.buyerNumber, archive: this.archive },
|
||||
});
|
||||
}
|
||||
|
||||
navigateToLandingPage() {
|
||||
|
||||
@@ -26,21 +26,22 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
|
||||
processingStatus$ = this._activatedRoute.params.pipe(map((params) => params?.processingStatus || undefined));
|
||||
|
||||
archive$ = this._activatedRoute.queryParams.pipe(map((params) => params?.archive || false));
|
||||
|
||||
compartmentCode$: Observable<string> = this._activatedRoute.params.pipe(
|
||||
map((params) => decodeURIComponent(params?.compartmentCode ?? '') || undefined)
|
||||
);
|
||||
|
||||
buyerNumber$ = this._activatedRoute.queryParams.pipe(map((params) => params.buyerNumber));
|
||||
|
||||
items$ = combineLatest([this.orderNumber$, this.compartmentCode$]).pipe(
|
||||
switchMap(([orderNumber, compartmentCode]) =>
|
||||
items$ = combineLatest([this.orderNumber$, this.compartmentCode$, this.archive$]).pipe(
|
||||
switchMap(([orderNumber, compartmentCode, archive]) =>
|
||||
compartmentCode
|
||||
? this._domainGoodsInService.getWarenausgabeItemByCompartment(compartmentCode)
|
||||
: this._domainGoodsInService.getWarenausgabeItemByOrderNumber(orderNumber)
|
||||
? this._domainGoodsInService.getWarenausgabeItemByCompartment(compartmentCode, archive)
|
||||
: this._domainGoodsInService.getWarenausgabeItemByOrderNumber(orderNumber, archive)
|
||||
),
|
||||
withLatestFrom(this.processingStatus$, this.buyerNumber$),
|
||||
map(([response, processingStatus, buyerNumber]) => {
|
||||
console.log(response, processingStatus, buyerNumber);
|
||||
return response.result.filter(
|
||||
(item) => item.processingStatus === +processingStatus && (!!buyerNumber ? item.buyerNumber === buyerNumber : true)
|
||||
);
|
||||
@@ -66,6 +67,7 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
const compartmentCode = this._activatedRoute.snapshot.params.compartmentCode;
|
||||
const processingStatus = this._activatedRoute.snapshot.params.processingStatus;
|
||||
const buyerNumber = this._activatedRoute.snapshot.queryParams.buyerNumber;
|
||||
const archive = this._activatedRoute.snapshot.queryParams.archive;
|
||||
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
|
||||
key: this.processId,
|
||||
name: 'Bearbeiten',
|
||||
@@ -73,7 +75,7 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
? `/kunde/${this.processId}/goods/out/details/compartment/${encodeURIComponent(compartmentCode)}/${processingStatus}/edit`
|
||||
: `/kunde/${this.processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}/edit`,
|
||||
section: 'customer',
|
||||
params: { buyerNumber },
|
||||
params: { buyerNumber, archive },
|
||||
tags: ['goods-out', 'edit', compartmentCode || orderNumber],
|
||||
});
|
||||
}
|
||||
@@ -83,13 +85,14 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
const compartmentCode = this._activatedRoute.snapshot.params.compartmentCode;
|
||||
const processingStatus = options?.processingStatus ? options.processingStatus : this._activatedRoute.snapshot.params.processingStatus;
|
||||
const buyerNumber = this._activatedRoute.snapshot.queryParams.buyerNumber;
|
||||
const archive = this._activatedRoute.snapshot.queryParams.archive;
|
||||
compartmentCode
|
||||
? this._router.navigate(
|
||||
[`/kunde/${this.processId}/goods/out/details/compartment/${encodeURIComponent(compartmentCode)}/${processingStatus}`],
|
||||
{ queryParams: { buyerNumber } }
|
||||
{ queryParams: { buyerNumber, archive } }
|
||||
)
|
||||
: this._router.navigate([`/kunde/${this.processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}`], {
|
||||
queryParams: { buyerNumber },
|
||||
queryParams: { buyerNumber, archive },
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +258,7 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
const orderNumber = orderItem.orderNumber;
|
||||
const processingStatus = orderItem.processingStatus;
|
||||
const compartmentCode = orderItem.compartmentCode;
|
||||
const archive = !!this._goodsOutSearchStore.filter?.getQueryParams()?.main_archive || false;
|
||||
|
||||
if (compartmentCode) {
|
||||
this._router.navigate(
|
||||
@@ -265,11 +266,16 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
{
|
||||
queryParams: {
|
||||
buyerNumber: orderItem.buyerNumber,
|
||||
archive,
|
||||
},
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this._router.navigate([`/kunde/${processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}`]);
|
||||
this._router.navigate([`/kunde/${processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}`], {
|
||||
queryParams: {
|
||||
archive,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export class TaskCalendarFilterComponent implements OnInit, OnDestroy {
|
||||
|
||||
filter$ = new BehaviorSubject<UiFilter>(undefined);
|
||||
|
||||
fetching$ = this.taskCalendarStore.selectFetching;
|
||||
fetching$ = this.taskCalendarStore.selectFetchingFilter;
|
||||
|
||||
message$ = this.taskCalendarStore.selectMessage;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export class PageTaskCalendarComponent implements OnInit, OnDestroy {
|
||||
taskCalendarKey = this._config.get('process.ids.taskCalendar');
|
||||
|
||||
hasFilter$ = combineLatest([
|
||||
this.taskCalendarStore.selectFetching,
|
||||
this.taskCalendarStore.selectFetchingFilter,
|
||||
this.taskCalendarStore.selectFilter,
|
||||
this.taskCalendarStore.selectInitialFilter,
|
||||
]).pipe(
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
[minDate]="minDate"
|
||||
[maxDate]="maxDate"
|
||||
[indicators]="indicators$ | async"
|
||||
[loading]="fetching$ | async"
|
||||
(selectedChange)="setSelectedDate($event)"
|
||||
(displayedChange)="setDisplayedDate($event)"
|
||||
></ui-calendar>
|
||||
|
||||
@@ -18,6 +18,8 @@ export class CalendarComponent implements OnInit {
|
||||
|
||||
readonly indicators$ = this.taskCalendarStore.selectCalendarIndicators;
|
||||
|
||||
readonly fetching$ = this.taskCalendarStore.selectFetchingItems;
|
||||
|
||||
readonly minDate = this.dateAdapter.addCalendarMonths(this.dateAdapter.today(), -6);
|
||||
|
||||
readonly maxDate = this.dateAdapter.addCalendarMonths(this.dateAdapter.today(), 6);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}
|
||||
|
||||
.empty-message {
|
||||
@apply bg-white text-center font-semibold text-inactive-customer py-10 rounded-card;
|
||||
@apply bg-white text-center font-semibold text-inactive-customer py-10 rounded-card mt-4;
|
||||
}
|
||||
|
||||
:host ::ng-deep ui-scroll-container .scroll-container {
|
||||
|
||||
@@ -27,7 +27,7 @@ export class TaskSearchComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
|
||||
searchResults$ = this.taskCalendarStore.searchResults$;
|
||||
searchResultsLength$ = this.searchResults$.pipe(map((r) => r.length || 0));
|
||||
fetching$ = this.taskCalendarStore.isSearching$;
|
||||
fetching$ = this.taskCalendarStore.selectFetchingSearch;
|
||||
|
||||
displayItems$ = this.searchResults$.pipe(
|
||||
map((r) => {
|
||||
@@ -94,7 +94,7 @@ export class TaskSearchComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
async search() {
|
||||
const hits = await this.taskCalendarStore.hits$.pipe(first()).toPromise();
|
||||
const results = await this.taskCalendarStore.searchResults$.pipe(first()).toPromise();
|
||||
const fetching = await this.taskCalendarStore.selectFetching.pipe(first()).toPromise();
|
||||
const fetching = await this.taskCalendarStore.selectFetchingSearch.pipe(first()).toPromise();
|
||||
|
||||
if (hits > results.length && !fetching) {
|
||||
this.taskCalendarStore.search({});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[displayed]="displayedDate$ | async"
|
||||
[minDate]="minDate"
|
||||
[maxDate]="maxDate"
|
||||
[loading]="fetching$ | async"
|
||||
[indicators]="indicators$ | async"
|
||||
(selectedChange)="setSelectedAndDisplayedDate({ selectedDate: $event })"
|
||||
(displayedChange)="setSelectedAndDisplayedDate({ displayDate: $event })"
|
||||
|
||||
@@ -23,7 +23,7 @@ export class TasksComponent implements OnInit {
|
||||
|
||||
readonly searchResults$ = this.taskCalendarStore.searchResults$;
|
||||
|
||||
readonly fetching$ = this.taskCalendarStore.select((s) => s.fetching);
|
||||
readonly fetching$ = this.taskCalendarStore.selectFetchingItems;
|
||||
|
||||
readonly minDate = this.dateAdapter.addCalendarMonths(this.dateAdapter.today(), -6);
|
||||
|
||||
|
||||
@@ -23,8 +23,9 @@ export interface TaskCalendarState {
|
||||
message: string;
|
||||
searchResults: DisplayInfoDTO[];
|
||||
searchTarget: string;
|
||||
fetching: boolean;
|
||||
isSearching: boolean;
|
||||
fetchingFilter: boolean;
|
||||
fetchingItems: boolean;
|
||||
fetchingSearch: boolean;
|
||||
hits: number;
|
||||
}
|
||||
|
||||
@@ -56,8 +57,6 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
|
||||
readonly searchTarget$ = this.select((s) => s.searchTarget);
|
||||
|
||||
readonly isSearching$ = this.select((s) => s.isSearching);
|
||||
|
||||
readonly selectCalendarIndicators = this.select(this.selectDisplayInfos, (displayItems) =>
|
||||
displayItems.reduce<CalendarIndicator[]>((agg, item) => {
|
||||
const calendarIndicator = this.mapDisplayInfoToCalendarIndicator(item);
|
||||
@@ -79,8 +78,11 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
|
||||
readonly selectFilter = this.select((s) => s.filter);
|
||||
|
||||
readonly selectFetching = this.select((s) => s.fetching);
|
||||
readonly fetching = this.get((s) => s.fetching);
|
||||
readonly selectFetchingFilter = this.select((s) => s.fetchingFilter);
|
||||
|
||||
readonly selectFetchingItems = this.select((s) => s.fetchingItems);
|
||||
|
||||
readonly selectFetchingSearch = this.select((s) => s.fetchingSearch);
|
||||
|
||||
readonly selectMessage = this.select((s) => s.message);
|
||||
|
||||
@@ -125,9 +127,10 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
initialFilter: undefined,
|
||||
filter: undefined,
|
||||
message: undefined,
|
||||
fetching: false,
|
||||
fetchingFilter: false,
|
||||
fetchingItems: false,
|
||||
fetchingSearch: false,
|
||||
searchResults: [],
|
||||
isSearching: false,
|
||||
hits: undefined,
|
||||
searchTarget: '',
|
||||
});
|
||||
@@ -170,7 +173,7 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
const currentBranch$ = this.domainTaskCalendarService.currentBranchId$.pipe(filter((f) => !!f));
|
||||
const selectFilter$ = this.selectFilter.pipe(filter((f) => !!f));
|
||||
return options$.pipe(
|
||||
tap(() => this.patchState({ isSearching: true, searchTarget: '' })),
|
||||
tap(() => this.patchState({ fetchingSearch: true, searchTarget: '' })),
|
||||
debounceTime(150),
|
||||
switchMap((options) =>
|
||||
zip(currentBranch$, selectFilter$).pipe(
|
||||
@@ -213,18 +216,18 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
this.patchState({
|
||||
searchResults,
|
||||
searchTarget,
|
||||
isSearching: false,
|
||||
fetchingSearch: false,
|
||||
message: undefined,
|
||||
hits: response.hits,
|
||||
});
|
||||
} else {
|
||||
this.uiModal.open({ content: UiMessageModalComponent, data: response });
|
||||
this.patchState({ searchResults: [], isSearching: false, message: 'Keine Suchergebnisse' });
|
||||
this.patchState({ searchResults: [], fetchingSearch: false, message: 'Keine Suchergebnisse' });
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.patchState({ searchResults: [], isSearching: false, message: 'Keine Suchergebnisse' });
|
||||
this.patchState({ searchResults: [], fetchingSearch: false, message: 'Keine Suchergebnisse' });
|
||||
}
|
||||
)
|
||||
);
|
||||
@@ -252,7 +255,7 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
const selectInitialFilter$ = this.selectInitialFilter.pipe(filter((f) => !!f));
|
||||
|
||||
return $.pipe(
|
||||
tap(() => this.patchState({ fetching: true })),
|
||||
tap(() => this.patchState({ fetchingItems: true })),
|
||||
debounceTime(250),
|
||||
switchMap((_) =>
|
||||
zip(currentBranch$, selectStartStop$, selectInitialFilter$).pipe(
|
||||
@@ -272,18 +275,18 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
(response) => {
|
||||
if (!response.error) {
|
||||
response = this.preparePreInfos(response);
|
||||
this.patchState({ displayInfos: response.result, fetching: false, message: undefined });
|
||||
this.patchState({ displayInfos: response.result, fetchingItems: false, message: undefined });
|
||||
} else {
|
||||
this.uiModal.open({
|
||||
content: UiMessageModalComponent,
|
||||
data: response,
|
||||
});
|
||||
this.patchState({ displayInfos: [], fetching: false, message: 'Keine Suchergebnisse' });
|
||||
this.patchState({ displayInfos: [], fetchingItems: false, message: 'Keine Suchergebnisse' });
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.patchState({ displayInfos: [], fetching: false, message: 'Keine Suchergebnisse' });
|
||||
this.patchState({ displayInfos: [], fetchingItems: false, message: 'Keine Suchergebnisse' });
|
||||
}
|
||||
)
|
||||
);
|
||||
@@ -305,15 +308,15 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
|
||||
|
||||
readonly loadFilter = this.effect(($: Observable<void>) =>
|
||||
$.pipe(
|
||||
tap(() => this.patchState({ fetching: true })),
|
||||
tap(() => this.patchState({ fetchingFilter: true })),
|
||||
switchMap((_) => this.domainTaskCalendarService.getSettings()),
|
||||
tapResponse(
|
||||
(response: QuerySettingsDTO) => {
|
||||
this.patchState({ filter: UiFilter.create(response), initialFilter: UiFilter.create(response), fetching: false });
|
||||
this.patchState({ filter: UiFilter.create(response), initialFilter: UiFilter.create(response), fetchingFilter: false });
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.patchState({ filter: undefined, initialFilter: undefined, fetching: false });
|
||||
this.patchState({ filter: undefined, initialFilter: undefined, fetchingFilter: false });
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -101,6 +101,12 @@ export class SharedGoodsInOutOrderDetailsCoversComponent extends ComponentStore<
|
||||
}
|
||||
return false;
|
||||
})
|
||||
?.filter((currentItem) => {
|
||||
const oderItemPaid = !!orderItems[0].features?.paid;
|
||||
const currentItemPaid = !!currentItem.features?.paid;
|
||||
|
||||
return oderItemPaid === currentItemPaid;
|
||||
})
|
||||
?.sort((a, b) => new Date(b.readyForPickUp).getTime() - new Date(a.readyForPickUp).getTime())
|
||||
?.find((_) => true)
|
||||
)
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
<div class="detail" data-detail-id="Benachrichtigung">
|
||||
<div class="label">Benachrichtigung</div>
|
||||
<div class="value">{{ (notificationsChannel$ | async | notificationsChannel) || '-' }}</div>
|
||||
<div class="value">{{ (notificationsChannel | notificationsChannel) || '-' }}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Input,
|
||||
OnChanges,
|
||||
SimpleChanges,
|
||||
OnDestroy,
|
||||
} from '@angular/core';
|
||||
import { CrmCustomerService } from '@domain/crm';
|
||||
import { DomainOmsService } from '@domain/oms';
|
||||
@@ -46,18 +47,7 @@ export class SharedGoodsInOutOrderDetailsHeaderComponent implements OnChanges {
|
||||
|
||||
preferredPickUpDate$ = new BehaviorSubject<Date>(undefined);
|
||||
|
||||
notificationsChannel$: Observable<NotificationChannel> = this.orderItem$.pipe(
|
||||
switchMap((oi) => {
|
||||
if (oi?.orderId) {
|
||||
return this.omsService.getNotifications(oi?.orderId).pipe(
|
||||
map((res) => res.selected),
|
||||
catchError(() => of(0 as NotificationChannel))
|
||||
);
|
||||
}
|
||||
|
||||
return of(0 as NotificationChannel);
|
||||
})
|
||||
);
|
||||
notificationsChannel: NotificationChannel = 0;
|
||||
|
||||
changeDateLoader$ = new BehaviorSubject<boolean>(false);
|
||||
changePreferredDateLoader$ = new BehaviorSubject<boolean>(false);
|
||||
@@ -91,12 +81,19 @@ export class SharedGoodsInOutOrderDetailsHeaderComponent implements OnChanges {
|
||||
private cdr: ChangeDetectorRef
|
||||
) {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
if (this.order) {
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.order) {
|
||||
this.findLatestPreferredPickUpDate();
|
||||
this.computeNotificationChannel();
|
||||
}
|
||||
}
|
||||
|
||||
computeNotificationChannel() {
|
||||
const order = this.order;
|
||||
this.notificationsChannel = order?.notificationChannels ?? 0;
|
||||
this.cdr.markForCheck();
|
||||
}
|
||||
|
||||
async updatePickupDeadline(deadline: Date) {
|
||||
this.changeDateLoader$.next(true);
|
||||
this.changeStatusDisabled$.next(true);
|
||||
@@ -186,10 +183,10 @@ export class SharedGoodsInOutOrderDetailsHeaderComponent implements OnChanges {
|
||||
|
||||
findLatestPreferredPickUpDate() {
|
||||
let latestDate;
|
||||
const subsetItems = this.order.items
|
||||
?.reduce<EntityDTOContainerOfOrderItemSubsetDTO[]>((agg, item) => [...agg, ...item.data.subsetItems], [])
|
||||
const subsetItems = this.order?.items
|
||||
?.flatMap((item) => item?.data?.subsetItems)
|
||||
?.filter((a) => !!a.data.preferredPickUpDate && (!this.selectedOrderItemId || this.selectedOrderItemId === a.data.id));
|
||||
if (subsetItems.length > 0) {
|
||||
if (subsetItems?.length > 0) {
|
||||
latestDate = new Date(
|
||||
subsetItems?.reduce((a, b) => {
|
||||
return new Date(a.data.preferredPickUpDate) > new Date(b.data.preferredPickUpDate) ? a : b;
|
||||
|
||||
@@ -56,7 +56,6 @@ export class SharedGoodsInOutOrderDetailsItemComponent extends ComponentStore<Sh
|
||||
if (this.get((s) => s.selected)) {
|
||||
this._host.selectOrderItem(this.orderItem, true);
|
||||
}
|
||||
this.loadReceipts();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +208,9 @@ export class SharedGoodsInOutOrderDetailsItemComponent extends ComponentStore<Sh
|
||||
|
||||
setMore(more: boolean) {
|
||||
this.patchState({ more });
|
||||
if (more && this.receipts.length === 0) {
|
||||
this.loadReceipts();
|
||||
}
|
||||
}
|
||||
|
||||
async openHistory() {
|
||||
|
||||
@@ -13,16 +13,14 @@ export class NotificationsChannelPipe implements PipeTransform {
|
||||
[16, 'Brief'],
|
||||
]);
|
||||
|
||||
transform(value: NotificationChannel = 0): any {
|
||||
transform(value: NotificationChannel = 0): string {
|
||||
const result: string[] = [];
|
||||
|
||||
const channelKeys = Array.from(NotificationsChannelPipe.channels.keys());
|
||||
|
||||
channelKeys.forEach((key) => {
|
||||
if (value & key) {
|
||||
result.push(NotificationsChannelPipe.channels.get(key));
|
||||
for (const [channel, name] of NotificationsChannelPipe.channels) {
|
||||
if (value & channel) {
|
||||
result.push(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result.join(' | ');
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="cell cell-first cell-calendar-week center">KW {{ week.week }}</div>
|
||||
<div class="cell cell-calendar-day center" [uiCalendarCell]="date" *ngFor="let date of week.dates" (click)="selectDate(date)">
|
||||
<div class="day center">{{ date | date: 'd' }}</div>
|
||||
<div class="indicators">
|
||||
<div class="indicators" *ngIf="!calendar.loading; else skeleton">
|
||||
<div
|
||||
class="indicator"
|
||||
*ngFor="let indicator of indicators$ | async | uiFilterIndicatorsByDate: date"
|
||||
@@ -19,4 +19,8 @@
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #skeleton>
|
||||
<ui-skeleton-loader class="flex items-center justify-center mt-1" width="30" height="20"></ui-skeleton-loader>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
@@ -36,6 +36,9 @@ export class UiCalendarComponent {
|
||||
}
|
||||
}
|
||||
|
||||
@Input()
|
||||
loading: boolean;
|
||||
|
||||
@Output()
|
||||
selectedChange = new EventEmitter<Date>();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { UiCommonModule } from '@ui/common';
|
||||
import { UiIconModule } from '@ui/icon';
|
||||
import { UiCalendarBodyComponent } from './calendar-body/calendar-body.component';
|
||||
import { UiCalendarCellDirective } from './calendar-body/calendar-cell.directive';
|
||||
@@ -16,7 +17,7 @@ import { UiCalendarComponent } from './ui-calendar.component';
|
||||
UiCalendarCellDirective,
|
||||
UiFilterIndicatorsByDatePipe,
|
||||
],
|
||||
imports: [CommonModule, UiIconModule, RouterModule],
|
||||
imports: [CommonModule, UiCommonModule, UiIconModule, RouterModule],
|
||||
exports: [UiCalendarComponent],
|
||||
})
|
||||
export class UiCalendarModule {}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
$ui-skeleton-animation-duration: 1.5s;
|
||||
$ui-skeleton-background: #e6eff9;
|
||||
$ui-skeleton-animation-duration: 1s;
|
||||
|
||||
.ui-skeleton-container {
|
||||
display: flex;
|
||||
@apply flex flex-col items-center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ui-skeleton-bar {
|
||||
background: #c4c9d0;
|
||||
display: flex;
|
||||
background: $ui-skeleton-background;
|
||||
animation: load $ui-skeleton-animation-duration linear infinite;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/>
|
||||
<div *ngIf="showHint" class="hint" (click)="focus()">{{ hint }}</div>
|
||||
</div>
|
||||
<button tabindex="1" class="clear-button" *ngIf="canClear" (click)="setQuery(''); focus()">
|
||||
<button type="button" tabindex="1" class="clear-button" *ngIf="canClear" (click)="setQuery(''); focus()">
|
||||
<ui-icon icon="close" size="22px"></ui-icon>
|
||||
</button>
|
||||
|
||||
|
||||
13628
package-lock.json
generated
13628
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"downlevelIteration": true,
|
||||
"target": "ES2022",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
|
||||
Reference in New Issue
Block a user