Merge tag 'post-2.1-hotfix' into develop (conflicts resolved)

This commit is contained in:
Michael Auer
2023-01-12 16:14:35 +01:00
33 changed files with 159 additions and 13737 deletions

View File

@@ -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) {

View File

@@ -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,
},

View File

@@ -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(() => {

View File

@@ -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));
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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:

View File

@@ -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(() => {});
}

View File

@@ -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));
}

View File

@@ -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() {

View File

@@ -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 },
});
}

View File

@@ -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,
},
});
}
}

View File

@@ -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;

View File

@@ -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(

View File

@@ -6,6 +6,7 @@
[minDate]="minDate"
[maxDate]="maxDate"
[indicators]="indicators$ | async"
[loading]="fetching$ | async"
(selectedChange)="setSelectedDate($event)"
(displayedChange)="setDisplayedDate($event)"
></ui-calendar>

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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({});

View File

@@ -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 })"

View File

@@ -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);

View File

@@ -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 });
}
)
)

View File

@@ -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)
)

View File

@@ -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

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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(' | ');
}

View File

@@ -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>

View File

@@ -36,6 +36,9 @@ export class UiCalendarComponent {
}
}
@Input()
loading: boolean;
@Output()
selectedChange = new EventEmitter<Date>();

View File

@@ -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 {}

View File

@@ -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;
}

View File

@@ -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
View File

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,7 @@
"experimentalDecorators": true,
"importHelpers": false,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"target": "ES2022",
"typeRoots": [
"node_modules/@types"