Compare commits

...

40 Commits

Author SHA1 Message Date
Michael Auer
aea6a0d131 Merge branch 'hotfix/3754-lieferschein-erneut-drucken' 2023-02-13 17:11:39 +01:00
Lorenz Hilpert
dc42107668 #3754 Lieferschein erneut drucken - CTA Fix 2023-01-17 16:11:53 +01:00
Michael Auer
a9479db5be Merge branch 'hotfix/post-2.1-hotfix' 2023-01-12 15:54:53 +01:00
Lorenz Hilpert
262e0c5e11 #3719 Benachrichtigungskanal wird nicht angezeigt 2022-12-19 16:10:53 +01:00
Lorenz Hilpert
8718dd8231 Merged PR 1459: Fix NotificationChannel Display in AHF
Fix NotificationChannel Display in AHF

Related work items: #3719
2022-12-16 14:26:32 +00:00
Lorenz Hilpert
0274b2af3b Merged PR 1458: #3718 Eingabe bei Enter bewirkt löschen und Eingabe Enter
#3718 Eingabe bei Enter bewirkt löschen und Eingabe Enter
2022-12-16 13:20:20 +00:00
Andreas Schickinger
2e286b2de3 Merged PR 1455: #3691 WA Kunden mit unterschiedlichen Kundennummern und gleicher Abholfachnummer
#3691 WA Kunden mit unterschiedlichen Kundennummern und gleicher Abholfachnummer

Related work items: #3691
2022-12-07 14:31:54 +00:00
Andreas Schickinger
168847b24a Merged PR 1454: #3661 AHF Feedbackmeldung beim Nachbestellen entfernt
#3661 AHF Feedbackmeldung beim Nachbestellen entfernt

Related work items: #3661
2022-11-29 14:22:04 +00:00
Andreas Schickinger
69c23a55f7 Merged PR 1453: #3682 AHF // Reservierungsliste - RadionButton ein- und ausblenden bei Paid/Unpaid
#3682 AHF // Reservierungsliste - Radion-Button ein- und ausblenden bei Bezahlt vs Nicht Bezahlt

Related work items: #3682
2022-11-29 14:17:52 +00:00
Andreas Schickinger
f344c2b0e8 Merged PR 1451: #3656 TK Loader Styling Anpassung
#3656 TK Loader Styling Anpassung

Related work items: #3656
2022-11-25 12:49:24 +00:00
Lorenz Hilpert
11819e59c6 #3654 Zubuchen zu Pay und Collect Artikeln verhindern 2022-11-25 13:47:30 +01:00
Lorenz Hilpert
caf7331d28 Fix Unit Test 2022-11-24 11:38:42 +01:00
Lorenz Hilpert
68e5926568 Isa Error Logging 2022-11-24 10:45:53 +01:00
Andreas Schickinger
9d46f49634 Merged PR 1450: #3656 TK Kalenderansicht Loading Feedback
#3656 TK Kalenderansicht Loading Feedback

Related work items: #3656
2022-11-22 17:18:44 +00:00
Lorenz Hilpert
daae9323e8 Merged PR 1447: #3643 API Calls in der WA und WE reduziert
#3643 API Calls in der WA und WE reduziert
2022-11-21 16:46:19 +00:00
Andreas Schickinger
80c425aa6f Merged PR 1449: #3645 TK Bugfix Initiales Loading
#3645 TK Bugfix Initiales Loading

Related work items: #3645
2022-11-21 15:37:00 +00:00
Andreas Schickinger
1cbe309778 Merged PR 1448: #3646 Hotfix TK Fehlender Abstand bei keinen Suchergebnissen
#3646 Hotfix TK Fehlender Abstand bei keinen Suchergebnissen

Related work items: #3646
2022-11-21 15:36:33 +00:00
Michael Auer
189dc64a0f Merge branch 'release/2.1' 2022-11-21 11:35:17 +01:00
Lorenz Hilpert
2f0ede7170 Merge branch 'develop' into release/2.1 2022-11-11 14:49:43 +01:00
Lorenz Hilpert
c7e444d446 #3617 CompartmentLabel für Kunden zwischenhspeichern 2022-11-11 10:56:18 +01:00
Lorenz Hilpert
f5ac916663 #3617 QR-Code Reservierungen 2022-11-10 15:02:27 +01:00
Lorenz Hilpert
b3b9f0223e #3629 - Scpeichern doppelclick abfangen 2022-11-10 14:08:50 +01:00
Lorenz Hilpert
70455df6d3 Merge branch 'develop' into release/2.1 2022-11-08 17:19:29 +01:00
Andreas Schickinger
b89889a3e9 Merged PR 1440: #3602 TK Kalenderansicht lädt nur noch die angezeigten Tage
#3602 TK Kalenderansicht lädt nur noch die angezeigten Tage

Related work items: #3602
2022-11-08 15:50:29 +00:00
Lorenz Hilpert
7ec00925ed Merged PR 1441: #3626 Fehlerbehebung bei der Dummy Anlage Änderung
#3626 Fehlerbehebung bei der Dummy Anlage Änderung
2022-11-08 15:40:07 +00:00
Andreas Schickinger
d3e3d127b3 Merged PR 1439: #3602 TK Performance
- Kein Reload mehr bei Wechsel zwischen Trefferliste/Kalenderansicht
- Suche startet ca. 150ms früher bei Page Load
- In der Wochenansicht wird nur noch die aktuelle Woche und 7 Tage in die Vergangenheit geladen (zuvor: aktuelle Woche + 7 Tage Vergangenheit/ 7 Tage Zukunft)
- In der Monatsansicht werden nur noch die Tage des Monats geladen (zuvor: aktueller Monat + 7 Tage Vergangenheit/ 7 Tage Zukunft
- Bugfix: doppelte Suche wurde ausgelöst, wenn man sucht -> zurück zur Übersicht klickt -> nochmal das gleiche sucht

Related work items: #3602
2022-11-08 09:13:21 +00:00
Nino Righi
11c4d8fb72 Merged PR 1438: #3608 Fix typo
#3608 Fix typo
2022-11-07 16:23:23 +00:00
Andreas Schickinger
9b02a19b9c Merged PR 1437: #3609 Remission Schriftfarbe bei Auswahl weiß
#3609 Remission Schriftfarbe bei Auswahl weiß

Related work items: #3609
2022-11-07 15:44:11 +00:00
Michael Auer
57262919b8 Merge tag '2.1.10' into develop 2022-11-07 15:07:34 +01:00
Michael Auer
f787a15347 Merge branch 'release/2.1' 2022-11-07 15:06:31 +01:00
Michael Auer
bc74eac86d Merge tag '2.1.2' into develop 2022-11-07 14:58:16 +01:00
Lorenz Hilpert
8a7b9de29d Merged PR 1436: #3615 Übernahme der Suchfeld eingabe in die Kundenanlage
#3615 Übernahme der Suchfeld eingabe in die Kundenanlage
2022-11-07 13:31:14 +00:00
Nino Righi
8efb87a1f7 Merged PR 1434: #3610 Fix Added Async Validator Function to p4m number form block
#3610 Fix Added Async Validator Function to p4m number form block
2022-11-03 18:21:07 +00:00
Andreas Schickinger
27ee667bfb Merged PR 1435: #3604 Kubi Checkmarks bei Kundentypanlage angepasst
#3604 Kubi Checkmarks bei Kundentypanlage angepasst

Related work items: #3604
2022-11-03 14:34:30 +00:00
Lorenz Hilpert
c64ff772e7 Merged PR 1433: Kundenanlage: Scanbutton für das scannen der Kundenkarte
Kundenanlage: Scanbutton für das scannen der Kundenkarte
2022-11-03 14:13:58 +00:00
Lorenz Hilpert
313efebb8b #3611 Dialog Anpassung handleAction 2022-11-02 16:47:58 +01:00
Lorenz Hilpert
9eee4fff6c Merged PR 1432: #3613 Wannennummer Scannen - Dialog erweitert
#3613 Wannennummer Scannen - Dialog erweitert
2022-11-02 15:15:48 +00:00
Lorenz Hilpert
b5a7c96181 Merge branch 'develop' into release/2.1 2022-11-02 15:00:54 +01:00
Lorenz Hilpert
5bea71e19e Merged PR 1431: #3611 Dummy Command angelegt
#3611 Dummy Command angelegt
2022-11-02 13:55:01 +00:00
Lorenz Hilpert
751e533dce Merge branch 'release/2.1' into develop 2022-10-28 11:20:42 +02:00
59 changed files with 560 additions and 374 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

@@ -1,5 +1,7 @@
import { Injectable } from '@angular/core';
import { ReceiptOrderItemSubsetReferenceValues, ReceiptService } from '@swagger/oms';
import { memorize } from '@utils/common';
import { shareReplay } from 'rxjs/operators';
@Injectable()
export class DomainReceiptService {
@@ -9,9 +11,12 @@ export class DomainReceiptService {
return this.receiptService.ReceiptCreateShippingNote2(params);
}
@memorize({ ttl: 1000 })
getReceipts(payload: ReceiptOrderItemSubsetReferenceValues) {
return this.receiptService.ReceiptGetReceiptsByOrderItemSubset({
payload: payload,
});
return this.receiptService
.ReceiptGetReceiptsByOrderItemSubset({
payload: payload,
})
.pipe(shareReplay(1));
}
}

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

@@ -9,6 +9,8 @@ import packageInfo from 'package';
import { interval, Observable, Subscription } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Platform } from '@angular/cdk/platform';
import { UserStateService } from '@swagger/isa';
import { IsaLogProvider } from './providers';
@Component({
selector: 'app-root',
@@ -38,16 +40,17 @@ export class AppComponent implements OnInit {
private readonly _renderer: Renderer2,
private readonly _swUpdate: SwUpdate,
private readonly _notifications: NotificationsHub,
private readonly _platform: Platform
private readonly _platform: Platform,
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 } from '@adapter/scan';
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

@@ -2,3 +2,4 @@ export * from './close.command';
export * from './create-customer.command';
export * from './create-kubi-customer.command';
export * from './print-kubi-agb.command';
export * from './remit.command';

View File

@@ -0,0 +1,14 @@
import { Injectable } from '@angular/core';
import { ActionHandler } from '@core/command';
/** Dummy Command um Fehlermeldungen aus dem Diloag zu verhinden */
@Injectable()
export class RemitCommand extends ActionHandler<any> {
constructor() {
super('remit');
}
handler(ctx: any): any {
return ctx;
}
}

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

@@ -1,11 +1,13 @@
import { HttpErrorResponse } from '@angular/common/http';
import { ErrorHandler, Injectable } from '@angular/core';
import { AuthService } from '@core/auth';
import { UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
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);
@@ -22,9 +24,10 @@ export class IsaErrorHandler implements ErrorHandler {
content: UiDialogModalComponent,
title: 'Sitzung abgelaufen',
data: {
handleCommand: false,
content: 'Sie waren zu lange nicht in der ISA aktiv. Bitte melden Sie sich erneut an',
actions: [{ command: 'CLOSE', selected: true, label: 'Erneut anmelden' }],
},
} as DialogModel,
})
.afterClosed$.toPromise();
@@ -32,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

@@ -0,0 +1,3 @@
import { ShoppingCartItemDTO } from '@swagger/checkout';
export interface CheckoutDummyData extends ShoppingCartItemDTO {}

View File

@@ -7,6 +7,7 @@ import { DateAdapter } from '@ui/common';
import { UiErrorModalComponent, UiModalRef, UiModalService } from '@ui/modal';
import { Subject } from 'rxjs';
import { first, shareReplay, takeUntil } from 'rxjs/operators';
import { CheckoutDummyData } from './checkout-dummy-data';
import { CheckoutDummyStore } from './checkout-dummy.store';
@Component({
@@ -41,7 +42,7 @@ export class CheckoutDummyComponent implements OnInit, OnDestroy {
private _dateAdapter: DateAdapter,
private _modal: UiModalService,
private _store: CheckoutDummyStore,
private _ref: UiModalRef<any, any>,
private _ref: UiModalRef<any, CheckoutDummyData>,
private readonly _applicationService: ApplicationService
) {}
@@ -57,18 +58,8 @@ export class CheckoutDummyComponent implements OnInit, OnDestroy {
if (!!this._ref?.data && Object.keys(this._ref?.data).length !== 0) {
const data = this._ref?.data;
const item = {
ean: data.ean || '',
name: data.name || '',
quantity: data.quantity || '',
estimatedShippingDate: data.estimatedShippingDate || this._dateAdapter.today().toISOString(),
contributors: data.contributors || '',
manufacturer: data.manufacturer || '',
supplier: data.supplier || 5,
price: data.price || '',
vat: data.vat || '',
};
this.populateFormFromModalData(item);
this._store.patchState({ shoppingCartItem: data });
this.populateFormFromModalData(data);
}
}
@@ -122,17 +113,22 @@ export class CheckoutDummyComponent implements OnInit, OnDestroy {
this.control.get('vat').setValue(item?.catalogAvailability?.price?.vat?.vatType);
}
populateFormFromModalData(item: any) {
this.control.get('name').setValue(item.name);
this.control.get('contributors').setValue(item.contributors);
this.control.get('manufacturer').setValue(item.manufacturer);
this.control.get('price').setValue(item.price ? String(item.price).replace('.', ',') : '');
this.control.get('vat').setValue(Number(item.vat));
populateFormFromModalData(item: CheckoutDummyData) {
let price = item?.availability?.price?.value?.value ?? '';
price = String(price).replace('.', ',');
let estimatedShippingDate = item?.estimatedShippingDate ?? this._dateAdapter.today().toISOString();
this.control.get('name').setValue(item?.product?.name ?? '');
this.control.get('contributors').setValue(item?.product?.contributors ?? '');
this.control.get('manufacturer').setValue(item?.product?.manufacturer ?? '');
this.control.get('price').setValue(price);
this.control.get('vat').setValue(Number(item?.availability?.price?.vat?.vatType));
this.control.get('quantity').setValue(item.quantity);
this.control.get('ean').setValue(item.ean);
this.control.get('supplier').setValue(Number(item.supplier));
this.control.get('estimatedShippingDate').setValue(item.estimatedShippingDate);
this.changeEstimatedShippingDate(new Date(item.estimatedShippingDate)); // Update View
this.control.get('ean').setValue(item?.product?.ean);
this.control.get('supplier').setValue(Number(item?.availability?.supplier?.id));
this.control.get('estimatedShippingDate').setValue(estimatedShippingDate);
this.changeEstimatedShippingDate(new Date(estimatedShippingDate)); // Update View
}
clearForm(withEan?: boolean) {

View File

@@ -7,7 +7,16 @@ import { DomainCheckoutService } from '@domain/checkout';
import { DomainOmsService } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ItemDTO } from '@swagger/cat';
import { AddToShoppingCartDTO, AvailabilityDTO, BranchDTO, DestinationDTO, PriceDTO, ProductDTO, PromotionDTO } from '@swagger/checkout';
import {
AddToShoppingCartDTO,
AvailabilityDTO,
BranchDTO,
DestinationDTO,
PriceDTO,
ProductDTO,
PromotionDTO,
ShoppingCartItemDTO,
} from '@swagger/checkout';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { Observable } from 'rxjs';
import { first, map, switchMap, tap, withLatestFrom } from 'rxjs/operators';
@@ -15,6 +24,7 @@ import { first, map, switchMap, tap, withLatestFrom } from 'rxjs/operators';
interface CheckoutDummyState {
item: ItemDTO;
shoppingCartItemId: number;
shoppingCartItem?: ShoppingCartItemDTO;
addToCartItem: AddToShoppingCartDTO;
estimatedShippingDate: string;
message: string;
@@ -297,6 +307,7 @@ export class CheckoutDummyStore extends ComponentStore<CheckoutDummyState> {
}
const availability = this._createAvailabilityDTO({ price, control });
const product = this._createProductDTO({ item, control });
const newItem: AddToShoppingCartDTO = {
quantity,
availability,
@@ -305,17 +316,11 @@ export class CheckoutDummyStore extends ComponentStore<CheckoutDummyState> {
destination: {
data: { target: 1, targetBranch: { id: branch.id } },
},
itemType: this.item.type,
itemType: this.item?.type ?? this.get((s) => s.shoppingCartItem)?.itemType,
};
if (update) {
const shoppingCart = await this._checkoutService
.getShoppingCart({ processId: this._application.activatedProcessId })
.pipe(first())
.toPromise();
const existingItem = shoppingCart?.items?.find(
(i) => i?.data?.product?.ean === i?.data?.product?.ean && i?.data?.features['orderType'] === 'Abholung'
);
const existingItem = this.get((s) => s.shoppingCartItem);
this.patchState({ addToCartItem: newItem, shoppingCartItemId: existingItem?.id });
}
this.patchState({ addToCartItem: newItem });

View File

@@ -21,6 +21,7 @@ import { emailNotificationValidator, mobileNotificationValidator } from '@shared
import { PurchasingOptionsListModalComponent } from '../modals/purchasing-options-list-modal';
import { PurchasingOptionsListModalData } from '../modals/purchasing-options-list-modal/purchasing-options-list-modal.data';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { CheckoutDummyData } from '../checkout-dummy/checkout-dummy-data';
export interface CheckoutReviewComponentState {
shoppingCart: ShoppingCartDTO;
@@ -409,7 +410,7 @@ export class CheckoutReviewComponent extends ComponentStore<CheckoutReviewCompon
}
}
openDummyModal(data?: any) {
openDummyModal(data?: CheckoutDummyData) {
this.uiModal.open({
content: CheckoutDummyComponent,
data,
@@ -417,18 +418,19 @@ export class CheckoutReviewComponent extends ComponentStore<CheckoutReviewCompon
}
changeDummyItem({ shoppingCartItem }: { shoppingCartItem: ShoppingCartItemDTO }) {
const data = {
price: shoppingCartItem?.availability?.price?.value?.value,
vat: shoppingCartItem?.availability?.price?.vat?.vatType,
supplier: shoppingCartItem?.availability?.supplier?.id,
estimatedShippingDate: shoppingCartItem?.estimatedShippingDate,
manufacturer: shoppingCartItem?.product?.manufacturer,
name: shoppingCartItem?.product?.name,
contributors: shoppingCartItem?.product?.contributors,
ean: shoppingCartItem?.product?.ean,
quantity: shoppingCartItem?.quantity,
};
this.openDummyModal(data);
// const data: CheckoutDummyData = {
// itemType: shoppingCartItem.itemType,
// price: shoppingCartItem?.availability?.price?.value?.value,
// vat: shoppingCartItem?.availability?.price?.vat?.vatType,
// supplier: shoppingCartItem?.availability?.supplier?.id,
// estimatedShippingDate: shoppingCartItem?.estimatedShippingDate,
// manufacturer: shoppingCartItem?.product?.manufacturer,
// name: shoppingCartItem?.product?.name,
// contributors: shoppingCartItem?.product?.contributors,
// ean: shoppingCartItem?.product?.ean,
// quantity: shoppingCartItem?.quantity,
// };
this.openDummyModal(shoppingCartItem);
}
async changeItem({ shoppingCartItem }: { shoppingCartItem: ShoppingCartItemDTO }) {

View File

@@ -378,6 +378,10 @@ export abstract class AbstractCreateCustomer implements OnInit, OnDestroy {
}
async save() {
if (this.busy$.value) {
return;
}
if (this.form.invalid) {
this.form.markAllAsTouched();
return;
@@ -385,6 +389,7 @@ export abstract class AbstractCreateCustomer implements OnInit, OnDestroy {
try {
this.busy$.next(true);
this.form.disable();
const customer: CustomerDTO = await this.getCustomerFromFormData();

View File

@@ -12,6 +12,7 @@
[data]="data.p4m"
(dataChanges)="patchFormData('p4m', $event)"
[focusAfterInit]="!data?._meta?.p4mRequired"
[asyncValidatorFns]="asyncLoyaltyCardValidatorFn"
>
</app-p4m-number-form-block>

View File

@@ -1,7 +1,7 @@
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
import { ValidatorFn, Validators } from '@angular/forms';
import { AsyncValidatorFn, ValidatorFn, Validators } from '@angular/forms';
import { Result } from '@domain/defs';
import { CustomerDTO, CustomerInfoDTO, KeyValueDTOOfStringAndString, PayerDTO } from '@swagger/crm';
import { CustomerDTO, KeyValueDTOOfStringAndString, PayerDTO } from '@swagger/crm';
import { NameFormBlockData } from '../../form-blocks/name/name-form-block-data';
import { AbstractCreateCustomer } from '../abstract-create-customer';
import { CreateP4MCustomerComponent } from '../create-p4m-customer';
@@ -42,6 +42,8 @@ export class UpdateP4MWebshopCustomerComponent extends AbstractCreateCustomer im
country: [Validators.required],
};
asyncLoyaltyCardValidatorFn: AsyncValidatorFn[] = [this.checkLoyalityCardValidator];
get billingAddress(): PayerDTO | undefined {
const payers = this.formData?._meta?.customerDto?.payers;

View File

@@ -6,6 +6,7 @@ import { UiFilter, UiFilterInputGroupMainComponent } from '@ui/filter';
import { isEqual } from 'lodash';
import { combineLatest, NEVER, Observable, Subject } from 'rxjs';
import { debounceTime, filter, map, switchMap, takeUntil } from 'rxjs/operators';
import { CustomerCreateFormData, encodeFormData } from '../../create-customer';
@Component({
selector: 'page-customer-search-main',
@@ -81,11 +82,16 @@ export class CustomerSearchMainComponent implements OnInit, OnDestroy {
}
updateCustomerCreateQueryParams(value: string) {
const data: CustomerCreateFormData = {};
if (this.isValidEmail(value)) {
this.customerCreateQueryParams = { email: value };
data.email = value;
} else {
this.customerCreateQueryParams = { lastName: value };
data.name = { lastName: value };
}
this.customerCreateQueryParams = {
formData: encodeFormData(data),
};
}
isValidEmail(email: string) {

View File

@@ -1,3 +1,6 @@
<ui-form-control label="Kundenkartencode" requiredMark="*">
<ui-form-control label="Kundenkartencode" requiredMark="*" class="flex-grow">
<input uiInput type="text" [formControl]="control" [tabindex]="tabIndexStart" [readonly]="readonly" [autofocus]="focusAfterInit" />
</ui-form-control>
<button type="button" *ngIf="!readonly && canScan()" (click)="scan()">
<ui-svg-icon icon="barcode-scan" size="32"></ui-svg-icon>
</button>

View File

@@ -1,3 +1,11 @@
:host {
@apply block;
@apply block relative;
}
button {
@apply absolute -right-2 top-0 h-14 w-14 border-none outline-none bg-transparent items-center justify-center rounded-full bg-brand;
ui-svg-icon {
@apply flex justify-center items-center text-white;
}
}

View File

@@ -1,6 +1,7 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { FormBlockControl } from '../form-block';
import { ScanAdapterService } from '@adapter/scan';
@Component({
selector: 'app-p4m-number-form-block',
@@ -13,7 +14,7 @@ export class P4mNumberFormBlockComponent extends FormBlockControl<string> {
return this.tabIndexStart;
}
constructor() {
constructor(private scanAdapter: ScanAdapterService, private changeDetectorRef: ChangeDetectorRef) {
super();
}
@@ -30,4 +31,15 @@ export class P4mNumberFormBlockComponent extends FormBlockControl<string> {
_patchValue(update: { previous: string; current: string }): void {
this.control.patchValue(update.current);
}
scan() {
this.scanAdapter.scan().subscribe((result) => {
this.control.patchValue(result);
this.changeDetectorRef.markForCheck();
});
}
canScan() {
return this.scanAdapter.isReady();
}
}

View File

@@ -6,9 +6,10 @@ import { ReactiveFormsModule } from '@angular/forms';
import { UiFormControlModule } from '@ui/form-control';
import { UiInputModule } from '@ui/input';
import { UiCommonModule } from '@ui/common';
import { UiIconModule } from '@ui/icon';
@NgModule({
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule],
imports: [CommonModule, UiCommonModule, ReactiveFormsModule, UiFormControlModule, UiInputModule, UiIconModule],
exports: [P4mNumberFormBlockComponent],
declarations: [P4mNumberFormBlockComponent],
})

View File

@@ -225,7 +225,7 @@ export class CustomerTypeSelectorComponent extends ComponentStore<CustomerTypeSe
} else {
// wenn customerType nicht gesetzt wird und p4mUser false ist,
// dann customerType auf den ersten verfügbaren setzen der nicht mit dem aktuellen customerType übereinstimmt.
this.customerType = first(this.enabledOptions.filter((o) => o.value !== this.customerType))?.value ?? this.customerType;
this.customerType = first(this.enabledOptions.filter((o) => o.value === this.customerType))?.value ?? this.customerType;
}
}

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

@@ -210,13 +210,32 @@ export class GoodsInReservationComponent implements OnInit, OnDestroy {
try {
for (const buyerNumber of buyerNumbers) {
const itemsToUpdateForEachCustomer = itemsToUpdate.filter((item) => item.buyerNumber === buyerNumber);
const itemQuantity = new Map(itemsToUpdateForEachCustomer.map((item) => [item.orderItemSubsetId, item.quantity]));
const data: OrderItemsContext = {
items: itemsToUpdateForEachCustomer,
shippingDelayComment: `Aktion: ${action.label}`,
itemQuantity,
};
await this._commandService.handleCommand(action.command, data);
const itemsToUpdateGroupedByCommand = itemsToUpdateForEachCustomer.reduce<Record<string, OrderItemListItemDTO[]>>((acc, item) => {
const command = item.actions.find((a) => a.value === action.value)?.command;
if (!acc[command]) {
acc[command] = [];
}
acc[command].push(item);
return acc;
}, {});
let compartmentCode: string;
for (const command of Object.keys(itemsToUpdateGroupedByCommand)) {
const itemsToUpdateForCommand = itemsToUpdateGroupedByCommand[command];
const itemQuantity = new Map(itemsToUpdateForCommand.map((item) => [item.orderItemSubsetId, item.quantity]));
const data: OrderItemsContext = {
items: itemsToUpdateForCommand,
shippingDelayComment: `Aktion: ${action.label}`,
itemQuantity,
compartmentCode,
};
const result = await this._commandService.handleCommand(command, data);
compartmentCode = result.compartmentCode;
}
}
this._store.reload();
this.unselectAll();

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

@@ -3,7 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import { BreadcrumbService } from '@core/breadcrumb';
import { Config } from '@core/config';
import { DomainRemissionService } from '@domain/remission';
import { UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
import { DialogModel, UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
import { UiSearchboxNextComponent } from '@ui/searchbox';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@@ -57,21 +57,22 @@ export class FinishShippingDocumentComponent implements OnInit, OnDestroy {
content: UiDialogModalComponent,
title: `Ist die Wannenummer korrekt oder möchten Sie die\nWannenummer erneut scannen?\n\n${query}`,
data: {
handleCommand: false,
actions: [
{ label: 'Erneut scannen', command: false },
{ label: 'Nummer korrekt', selected: true, command: true },
{ label: 'Erneut scannen', command: 'rescan' },
{ label: 'Nummer korrekt', selected: true, command: 'correct' },
],
},
} as DialogModel,
});
modal.afterClosed$.pipe(takeUntil(this._onDestroy$)).subscribe(async (result) => {
if (result?.data) {
if (result?.data === 'correct') {
if (await this.completeReceipt(query)) {
await this.completeReturn();
}
await this.navigateToFinishRemission();
} else {
} else if (result?.data === 'rescan') {
this.searchboxComponent.clear();
}
});

View File

@@ -8,7 +8,7 @@ import {
ReturnItemDTO,
ReturnSuggestionDTO,
} from '@swagger/remi';
import { UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
import { DialogModel, UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
import { mapFromReturnItemDTO, mapFromReturnSuggestionDTO } from 'apps/domain/remission/src/lib/mappings';
import { BehaviorSubject, Subject } from 'rxjs';
import { first, takeUntil } from 'rxjs/operators';
@@ -93,11 +93,12 @@ export class RemissionListItemComponent implements OnDestroy {
} zu\nremittieren. Sind wirklich alle Exemplare in ${
this.item.placementType && this.item.placementType === 'Stapel' ? 'dem Stapel' : 'der Leistung'
}?`,
handleCommand: false,
actions: [
{ label: 'Ja', selected: true, command: 'remit' },
{ label: 'Abbrechen', command: 'close' },
],
},
} as DialogModel,
});
modal.afterClosed$.pipe(takeUntil(this._onDestroy$)).subscribe((result) => {

View File

@@ -25,7 +25,7 @@
<div class="inline-flex flex-row bg-white rounded-md mt-4">
<button
class="w-48 py-2 bg-white text-black rounded-md font-bold"
class="w-48 py-2 bg-white rounded-md font-bold"
type="button"
*ngFor="let source of sources$ | async"
[class.bg-active-branch]="(selectedSource$ | async) === source"

View File

@@ -40,7 +40,7 @@ export class TaskSearchbarComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.control.patchValue(this.getControlValueFromQuery());
this.control.valueChanges.pipe(takeUntil(this._onDestroy$), debounceTime(500)).subscribe((value) => {
this.control.valueChanges.pipe(takeUntil(this._onDestroy$), debounceTime(250)).subscribe((value) => {
this.setValueInFilter(value);
this._cdr.markForCheck();
});
@@ -86,7 +86,8 @@ export class TaskSearchbarComponent implements OnInit, OnDestroy {
this.navigate('/filiale/task-calendar/search', params);
// ActivatedRouteChange wird nicht aufgerufen, wenn sich die URL nicht verändert. In dem Fall erneute Suche ausführen
if (isEqual(filter.getQueryParams(), this._activatedRoute.snapshot.queryParams)) {
const isSearchPage = this._router.url.startsWith('/filiale/task-calendar/search?');
if (isSearchPage && isEqual(filter.getQueryParams(), this._activatedRoute.snapshot.queryParams)) {
this.taskCalendarStore.search({ clear: true });
}
}

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;
@@ -66,7 +66,8 @@ export class TaskCalendarFilterComponent implements OnInit, OnDestroy {
this.navigate('/filiale/task-calendar/search', queryParams);
// ActivatedRouteChange wird nicht aufgerufen, wenn sich die URL nicht verändert. In dem Fall erneute Suche ausführen
if (isEqual(filters.getQueryParams(), this._activatedRoute.snapshot.queryParams)) {
const isSearchPage = this._router.url.startsWith('/filiale/task-calendar/search?');
if (isSearchPage && isEqual(filters.getQueryParams(), this._activatedRoute.snapshot.queryParams)) {
this.taskCalendarStore.search({ clear: true });
}

View File

@@ -2,7 +2,7 @@ import { Component, ViewChild, ElementRef, OnInit, OnDestroy } from '@angular/co
import { ActivatedRoute } from '@angular/router';
import { Config } from '@core/config';
import { UiFilter } from '@ui/filter';
import { isEqual } from 'lodash';
import { delay, isEqual } from 'lodash';
import { BehaviorSubject, combineLatest, Subject } from 'rxjs';
import { first, map, shareReplay, takeUntil, debounceTime } from 'rxjs/operators';
import { TaskSearchbarComponent } from './components/task-searchbar/task-searchbar.component';
@@ -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(
@@ -46,13 +46,15 @@ export class PageTaskCalendarComponent implements OnInit, OnDestroy {
this.searchbar?.focus();
});
this._activatedRoute.queryParams.pipe(takeUntil(this._onDestroy$), debounceTime(500)).subscribe(async (queryParams) => {
this._activatedRoute.queryParams.pipe(takeUntil(this._onDestroy$), debounceTime(250)).subscribe(async (queryParams) => {
const filters = UiFilter.create(await this.taskCalendarStore.selectInitialFilter.pipe(first()).toPromise());
if (queryParams) {
filters.fromQueryParams(queryParams);
}
this.taskCalendarStore.setFilter({ filters });
});
this.taskCalendarStore.loadItems();
}
ngOnDestroy(): void {

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) => {
@@ -70,7 +70,7 @@ export class TaskSearchComponent implements OnInit, OnDestroy, AfterViewInit {
) {}
ngOnInit() {
this._activatedRoute.queryParams.pipe(takeUntil(this._onDestroy$), debounceTime(500)).subscribe(async (queryParams) => {
this._activatedRoute.queryParams.pipe(takeUntil(this._onDestroy$), debounceTime(250)).subscribe(async (queryParams) => {
this.taskCalendarStore.search({ clear: true });
this.updateBreadcrumb(queryParams);
});
@@ -79,7 +79,7 @@ export class TaskSearchComponent implements OnInit, OnDestroy, AfterViewInit {
}
ngAfterViewInit(): void {
this.taskCalendarStore.searchTarget$.pipe(takeUntil(this._onDestroy$), debounceTime(500)).subscribe((target) => {
this.taskCalendarStore.searchTarget$.pipe(takeUntil(this._onDestroy$), debounceTime(250)).subscribe((target) => {
setTimeout(() => {
document.getElementById(target)?.scrollIntoView();
}, 0);
@@ -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);
@@ -50,7 +50,6 @@ export class TasksComponent implements OnInit {
this.updateBreadcrumb({});
}
this.taskCalendarStore.loadItems();
this.removeSearchBreadcrumbs();
this.taskCalendarStore.resetSearch();

View File

@@ -7,8 +7,8 @@ import { DateAdapter } from '@ui/common';
import { Filter, FilterOption, SelectFilter, UiFilter, UiFilterMappingService } from '@ui/filter';
import { UiMessageModalComponent, UiModalRef, UiModalResult, UiModalService } from '@ui/modal';
import { clone } from 'lodash';
import { Observable, Subject } from 'rxjs';
import { debounceTime, map, switchMap, tap, withLatestFrom, first, filter } from 'rxjs/operators';
import { Observable, Subject, zip } from 'rxjs';
import { debounceTime, map, switchMap, tap, withLatestFrom, first, takeWhile, filter } from 'rxjs/operators';
import { InfoModalComponent } from './modals/info/info-modal.component';
import { PreInfoModalComponent } from './modals/preinfo/preinfo-modal.component';
import { TaskModalComponent } from './modals/task/task-modal.component';
@@ -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);
@@ -91,21 +93,21 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
const fdow = this.dateAdapter.getFirstDateOfWeek(displayedDate);
const fdowWithOffset = this.dateAdapter.addCalendarDays(fdow, -7);
const ldow = this.dateAdapter.getLastDateOfWeek(displayedDate);
const ldowWithOffset = this.dateAdapter.addCalendarDays(ldow, 7);
return {
start: fdowWithOffset,
stop: ldowWithOffset,
stop: ldow,
};
} else {
const fdom = this.dateAdapter.getFirstDateOfMonth(displayedDate);
const fdomWithOffset = this.dateAdapter.addCalendarDays(fdom, -7);
const ldom = this.dateAdapter.getLastDateOfMonth(displayedDate);
const ldomWithOffset = this.dateAdapter.addCalendarDays(ldom, 7);
return {
start: fdomWithOffset,
stop: ldomWithOffset,
};
const month = this.dateAdapter.getDatesAndCalendarWeeksForMonth(displayedDate);
if (month.length > 0) {
const firstWeekOfMonth = month[0];
const lastWeekOfMonth = month[month.length - 1];
return {
start: firstWeekOfMonth.dates[0],
stop: lastWeekOfMonth.dates[lastWeekOfMonth.dates.length - 1],
};
}
}
});
@@ -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: '',
});
@@ -166,68 +169,73 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
searchTarget,
}));
readonly search = this.effect((options$: Observable<{ clear?: boolean }>) =>
options$.pipe(
tap(() => this.patchState({ isSearching: true, searchTarget: '' })),
debounceTime(500),
withLatestFrom(this.domainTaskCalendarService.currentBranchId$, this.selectFilter),
switchMap(([options, branchId, filter]) => {
const querytoken = {
...filter?.getQueryToken(),
// Paging ist vorbereitet aber vorerst deaktiviert
// skip: results.length || 0,
// take: 50,
};
search = this.effect((options$: Observable<{ clear?: boolean }>) => {
const currentBranch$ = this.domainTaskCalendarService.currentBranchId$.pipe(filter((f) => !!f));
const selectFilter$ = this.selectFilter.pipe(filter((f) => !!f));
return options$.pipe(
tap(() => this.patchState({ fetchingSearch: true, searchTarget: '' })),
debounceTime(150),
switchMap((options) =>
zip(currentBranch$, selectFilter$).pipe(
switchMap(([branchId, filter]) => {
const querytoken = {
...filter?.getQueryToken(),
};
// Im Zeitraum von 6 Wochen in der Vergangenheit und 2 Wochen in der Zukunft abfragen
const start = this.dateAdapter.addCalendarDays(this.dateAdapter.today(), -42);
const stop = this.dateAdapter.addCalendarDays(this.dateAdapter.today(), 14);
return this.domainTaskCalendarService
.getInfos({
...querytoken,
filter: {
timespan: `"${start.toISOString()}"-"${stop?.toISOString()}"`,
...querytoken?.filter,
branch_id: String(branchId),
},
// Im Zeitraum von 6 Wochen in der Vergangenheit und 2 Wochen in der Zukunft abfragen
const start = this.dateAdapter.addCalendarDays(this.dateAdapter.today(), -42);
const stop = this.dateAdapter.addCalendarDays(this.dateAdapter.today(), 14);
return this.domainTaskCalendarService
.getInfos({
...querytoken,
filter: {
timespan: `"${start.toISOString()}"-"${stop?.toISOString()}"`,
...querytoken?.filter,
branch_id: String(branchId),
},
})
.pipe(
tapResponse(
(response) => {
if (!response.error) {
response = this.preparePreInfos(response);
const results = this.get((s) => s.searchResults);
const searchResults = results.length > 0 && !options?.clear ? [...results, ...response.result] : [...response.result];
const sorted = searchResults.sort((a, b) =>
this.dateAdapter.findClosestDate(
new Date(a.taskDate || a.publicationDate),
new Date(b.taskDate || b.publicationDate)
)
);
const searchTarget =
sorted?.length > 0
? this.domainTaskCalendarService.getDateGroupKey(sorted[0].taskDate || sorted[0].publicationDate)
: '';
this.patchState({
searchResults,
searchTarget,
fetchingSearch: false,
message: undefined,
hits: response.hits,
});
} else {
this.uiModal.open({ content: UiMessageModalComponent, data: response });
this.patchState({ searchResults: [], fetchingSearch: false, message: 'Keine Suchergebnisse' });
}
},
(error) => {
console.error(error);
this.patchState({ searchResults: [], fetchingSearch: false, message: 'Keine Suchergebnisse' });
}
)
);
})
.pipe(
tapResponse(
(response) => {
if (!response.error) {
response = this.preparePreInfos(response);
const results = this.get((s) => s.searchResults);
const searchResults = results.length > 0 && !options?.clear ? [...results, ...response.result] : [...response.result];
const sorted = searchResults.sort((a, b) =>
this.dateAdapter.findClosestDate(new Date(a.taskDate || a.publicationDate), new Date(b.taskDate || b.publicationDate))
);
const searchTarget =
sorted?.length > 0
? this.domainTaskCalendarService.getDateGroupKey(sorted[0].taskDate || sorted[0].publicationDate)
: '';
this.patchState({
searchResults,
searchTarget,
isSearching: false,
message: undefined,
hits: response.hits,
});
} else {
this.uiModal.open({ content: UiMessageModalComponent, data: response });
this.patchState({ searchResults: [], isSearching: false, message: 'Keine Suchergebnisse' });
}
},
(error) => {
console.error(error);
this.patchState({ searchResults: [], isSearching: false, message: 'Keine Suchergebnisse' });
}
)
);
})
)
);
)
)
);
});
resetSearch() {
this.patchState({ searchResults: [], hits: undefined });
@@ -241,45 +249,52 @@ export class TaskCalendarStore extends ComponentStore<TaskCalendarState> impleme
this._searchbarFocus$.complete();
}
readonly loadItems = this.effect(($: Observable<void>) =>
$.pipe(
tap(() => this.patchState({ fetching: true })),
debounceTime(500),
withLatestFrom(this.domainTaskCalendarService.currentBranchId$, this.selectStartStop, this.selectInitialFilter),
switchMap(([_, branchId, date, filter]) => {
const querytoken = { ...filter?.getQueryToken() };
return this.domainTaskCalendarService
.getInfos({
...querytoken,
filter: {
...querytoken?.filter,
branch_id: String(branchId),
timespan: `"${date?.start?.toISOString()}"-"${date.stop?.toISOString()}"`,
},
loadItems = this.effect(($: Observable<void>) => {
const currentBranch$ = this.domainTaskCalendarService.currentBranchId$.pipe(filter((f) => !!f));
const selectStartStop$ = this.selectStartStop.pipe(filter((f) => !!f));
const selectInitialFilter$ = this.selectInitialFilter.pipe(filter((f) => !!f));
return $.pipe(
tap(() => this.patchState({ fetchingItems: true })),
debounceTime(250),
switchMap((_) =>
zip(currentBranch$, selectStartStop$, selectInitialFilter$).pipe(
switchMap(([branchId, date, filter]) => {
const querytoken = { ...filter?.getQueryToken() };
return this.domainTaskCalendarService
.getInfos({
...querytoken,
filter: {
...querytoken?.filter,
branch_id: String(branchId),
timespan: `"${date?.start?.toISOString()}"-"${date.stop?.toISOString()}"`,
},
})
.pipe(
tapResponse(
(response) => {
if (!response.error) {
response = this.preparePreInfos(response);
this.patchState({ displayInfos: response.result, fetchingItems: false, message: undefined });
} else {
this.uiModal.open({
content: UiMessageModalComponent,
data: response,
});
this.patchState({ displayInfos: [], fetchingItems: false, message: 'Keine Suchergebnisse' });
}
},
(error) => {
console.error(error);
this.patchState({ displayInfos: [], fetchingItems: false, message: 'Keine Suchergebnisse' });
}
)
);
})
.pipe(
tapResponse(
(response) => {
if (!response.error) {
response = this.preparePreInfos(response);
this.patchState({ displayInfos: response.result, fetching: false, message: undefined });
} else {
this.uiModal.open({
content: UiMessageModalComponent,
data: response,
});
this.patchState({ displayInfos: [], fetching: false, message: 'Keine Suchergebnisse' });
}
},
(error) => {
console.error(error);
this.patchState({ displayInfos: [], fetching: false, message: 'Keine Suchergebnisse' });
}
)
);
})
)
);
)
)
);
});
preparePreInfos(response) {
const preInfos = response.result.filter((info) => this.domainTaskCalendarService.getInfoType(info) === 'PreInfo');
@@ -293,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,13 +8,15 @@ import {
Input,
OnChanges,
SimpleChanges,
OnDestroy,
} from '@angular/core';
import { CrmCustomerService } from '@domain/crm';
import { DomainOmsService } from '@domain/oms';
import { NotificationChannel } from '@swagger/crm';
import { KeyValueDTOOfStringAndString, OrderDTO, OrderItemListItemDTO } from '@swagger/oms';
import { DateAdapter } from '@ui/common';
import { cloneDeep } from 'lodash';
import { BehaviorSubject, combineLatest, of } from 'rxjs';
import { BehaviorSubject, combineLatest, Subject } from 'rxjs';
import { catchError, filter, first, map, shareReplay, switchMap } from 'rxjs/operators';
import { SharedGoodsInOutOrderDetailsComponent } from '../goods-in-out-order-details.component';
@@ -45,18 +47,7 @@ export class SharedGoodsInOutOrderDetailsHeaderComponent implements OnChanges {
preferredPickUpDate$ = new BehaviorSubject<Date>(undefined);
notificationsChannel$ = this.orderItem$.pipe(
switchMap((oi) => {
if (oi?.orderId) {
return this.omsService.getNotifications(oi?.orderId).pipe(
map((res) => res.selected),
catchError(() => of(0))
);
}
return of({ selected: 0 });
})
);
notificationsChannel: NotificationChannel = 0;
changeDateLoader$ = new BehaviorSubject<boolean>(false);
changePreferredDateLoader$ = new BehaviorSubject<boolean>(false);
@@ -90,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);
@@ -185,10 +183,10 @@ export class SharedGoodsInOutOrderDetailsHeaderComponent implements OnChanges {
findLatestPreferredPickUpDate() {
let latestDate;
const subsetItems = this.order.items
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

@@ -18,6 +18,7 @@ import { OrderDTO, OrderItemListItemDTO, ReceiptDTO, ReceiptType } from '@swagge
import { UiModalService } from '@ui/modal';
import { isEqual } from 'lodash';
import { combineLatest, NEVER } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { catchError, filter, first, map, switchMap, withLatestFrom } from 'rxjs/operators';
import { SharedGoodsInOutOrderDetailsStore } from '../goods-in-out-order-details.store';
@@ -56,7 +57,6 @@ export class SharedGoodsInOutOrderDetailsItemComponent extends ComponentStore<Sh
if (this.get((s) => s.selected)) {
this._host.selectOrderItem(this.orderItem, true);
}
this.loadReceipts();
}
}
@@ -160,11 +160,11 @@ export class SharedGoodsInOutOrderDetailsItemComponent extends ComponentStore<Sh
this._host.selectOrderItem(this.orderItem, false);
}
loadReceipts = this.effect(($) =>
$.pipe(
loadReceipts = this.effect((done$: Observable<(receipts: ReceiptDTO[]) => void | undefined>) =>
done$.pipe(
withLatestFrom(this.orderItem$),
filter(([_, orderItem]) => !!orderItem),
switchMap(([_, orderItem]) =>
switchMap(([done, orderItem]) =>
this._domainReceiptService
.getReceipts({
receiptType: 65 as ReceiptType,
@@ -174,9 +174,18 @@ export class SharedGoodsInOutOrderDetailsItemComponent extends ComponentStore<Sh
.pipe(
tapResponse(
(res) => {
this.receipts = res.result.map((r) => r.item3?.data).filter((f) => !!f);
const receipts = res.result.map((r) => r.item3?.data).filter((f) => !!f);
this.receipts = receipts;
if (typeof done === 'function') {
done?.(receipts);
}
},
(err) => {
if (typeof done === 'function') {
done?.([]);
}
},
(err) => {},
() => {}
)
)
@@ -204,6 +213,9 @@ export class SharedGoodsInOutOrderDetailsItemComponent extends ComponentStore<Sh
setMore(more: boolean) {
this.patchState({ more });
if (more && this.receipts.length === 0) {
this.loadReceipts(undefined);
}
}
openHistory() {

View File

@@ -3,8 +3,9 @@ import { Component, ChangeDetectionStrategy, ContentChildren, QueryList } from '
import { BreadcrumbService } from '@core/breadcrumb';
import { CommandService } from '@core/command';
import { OrderItemsContext } from '@domain/oms';
import { KeyValueDTOOfStringAndString, OrderItemListItemDTO } from '@swagger/oms';
import { KeyValueDTOOfStringAndString, OrderItemListItemDTO, ReceiptDTO } from '@swagger/oms';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { unionBy } from 'lodash';
import { BehaviorSubject, combineLatest, merge, of, Subscription } from 'rxjs';
import { first, map, switchMap } from 'rxjs/operators';
import { SharedGoodsInOutOrderDetailsCoversComponent } from './goods-in-out-order-details-covers';
@@ -163,6 +164,19 @@ export class SharedGoodsInOutOrderDetailsComponent extends SharedGoodsInOutOrder
this.patchState({ fetchPartial: true });
return;
}
let receipts: ReceiptDTO[] = [];
if (action.command.includes('PRINT_SHIPPINGNOTE')) {
const receiptsPromise = this.orderDetailsItemComponents.toArray().map(
(timeComponent) =>
new Promise<ReceiptDTO[]>((resolve) => {
timeComponent.loadReceipts((r) => resolve(r));
})
);
receipts = await Promise.all(receiptsPromise).then((r) => r.flat());
receipts = unionBy(receipts, 'id');
}
// #2737 Bei Zubuchen kein Abholfachzettel ausdrucken
let command = action.command;
@@ -179,7 +193,7 @@ export class SharedGoodsInOutOrderDetailsComponent extends SharedGoodsInOutOrder
compartmentCode:
action.command.includes('PRINT_PRICEDIFFQRCODELABEL') && !compartmentCode ? this.orderItems[0]?.compartmentCode : compartmentCode,
itemQuantity: this.getItemQuantityMap(),
receipts: this.receipts,
receipts,
};
try {
commandData = await this.commandService.handleCommand(command, commandData);

View File

@@ -134,7 +134,7 @@
<input uiInput formControlName="price" />
</ui-form-control>
<ui-form-control label="IBAN/EAN" [clearable]="true" variant="inline" requiredMark=" *">
<ui-form-control label="ISBN/EAN" [clearable]="true" variant="inline" requiredMark=" *">
<input uiInput formControlName="ean" />
</ui-form-control>

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,15 +1,14 @@
$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

@@ -6,7 +6,7 @@ import { UISvgIconComponent } from './svg-icon.component';
import { IconRegistry } from './icon-registry';
import { UI_ICON_CFG } from './tokens';
import { UiIconConfig } from './icon-config';
import { mdiAccount, mdiPackageVariantClosed } from '@mdi/js';
import { mdiAccount, mdiPackageVariantClosed, mdiMagnify, mdiBarcodeScan } from '@mdi/js';
export function _rootIconRegistryFactory(config: UiIconConfig): IconRegistry {
const registry = new IconRegistry();
@@ -28,6 +28,8 @@ const DEFAULT_ICON_CONFIG: UiIconConfig = {
icons: [
{ name: 'account', data: mdiAccount },
{ name: 'package-variant-closed', data: mdiPackageVariantClosed },
{ name: 'magnify', data: mdiMagnify },
{ name: 'barcode-scan', data: mdiBarcodeScan },
],
};

View File

@@ -19,6 +19,10 @@ export class UiDialogModalComponent implements OnInit {
return;
}
this.modalRef.close(await this._command.handleCommand(command, this.modalRef.data.context));
if (this.modalRef.data.handleCommand ?? true) {
await this._command.handleCommand(command, this.modalRef.data.context);
}
this.modalRef.close(command);
}
}

View File

@@ -1,13 +1,17 @@
import { DialogSettings, KeyValueDTOOfStringAndString } from '@swagger/crm';
export interface DialogModel<T> {
export interface DialogModel<T = any> {
actions?: Array<KeyValueDTOOfStringAndString>;
actionsRequired?: number;
area?: string;
content?: string;
description?: string;
settings: DialogSettings;
settings?: DialogSettings;
subtitle?: string;
title?: string;
context?: T;
/**
* default: true
*/
handleCommand?: boolean;
}

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>

134
package-lock.json generated
View File

@@ -2932,7 +2932,7 @@
"@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
"@types/lodash": {
@@ -3937,7 +3937,7 @@
"bonjour": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
"integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==",
"integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
"dev": true,
"requires": {
"array-flatten": "^2.1.0",
@@ -4124,7 +4124,7 @@
"call-me-maybe": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
"integrity": "sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==",
"integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
"dev": true
},
"callsites": {
@@ -4430,7 +4430,7 @@
"collection-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
"integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==",
"integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
"dev": true,
"requires": {
"map-visit": "^1.0.0",
@@ -5131,7 +5131,7 @@
"css-parse": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz",
"integrity": "sha512-UNIFik2RgSbiTwIW1IsFwXWn6vs+bYdq83LKTSOsx7NJR7WII9dxewkHLltfTLVppoUApHV0118a4RZRI9FLwA==",
"integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=",
"dev": true,
"requires": {
"css": "^2.0.0"
@@ -5384,7 +5384,7 @@
"decamelize-keys": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
"integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==",
"integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
"dev": true,
"requires": {
"decamelize": "^1.1.0",
@@ -5394,7 +5394,7 @@
"map-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"dev": true
}
}
@@ -5444,7 +5444,7 @@
"defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
"integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==",
"integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
"dev": true,
"requires": {
"clone": "^1.0.2"
@@ -6263,7 +6263,7 @@
"expand-brackets": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
"integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==",
"integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
"dev": true,
"requires": {
"debug": "^2.3.3",
@@ -6287,7 +6287,7 @@
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
"integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
"dev": true,
"requires": {
"is-descriptor": "^0.1.0"
@@ -6296,7 +6296,7 @@
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
@@ -6305,7 +6305,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
}
}
@@ -6740,7 +6740,7 @@
"fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
"integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==",
"integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
"dev": true,
"requires": {
"map-cache": "^0.2.2"
@@ -7812,7 +7812,7 @@
"indexes-of": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
"integrity": "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==",
"integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
"dev": true
},
"indexof": {
@@ -9188,7 +9188,7 @@
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
"lodash.truncate": {
@@ -9200,7 +9200,7 @@
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=",
"dev": true
},
"log-symbols": {
@@ -9383,7 +9383,7 @@
"map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
"integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==",
"integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
"dev": true
},
"map-obj": {
@@ -9395,7 +9395,7 @@
"map-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
"integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
"integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
"dev": true,
"requires": {
"object-visit": "^1.0.0"
@@ -9499,7 +9499,7 @@
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
"integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==",
"integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
"dev": true,
"requires": {
"errno": "^0.1.3",
@@ -9902,7 +9902,7 @@
"multicast-dns-service-types": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
"integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
"dev": true
},
"multimatch": {
@@ -10355,7 +10355,7 @@
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
"dev": true,
"requires": {
"path-key": "^2.0.0"
@@ -10403,7 +10403,7 @@
"object-copy": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
"integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==",
"integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
"dev": true,
"requires": {
"copy-descriptor": "^0.1.0",
@@ -10414,7 +10414,7 @@
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
"integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
"dev": true,
"requires": {
"is-descriptor": "^0.1.0"
@@ -10423,7 +10423,7 @@
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "^1.1.5"
@@ -10462,7 +10462,7 @@
"object-visit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
"integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==",
"integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
"dev": true,
"requires": {
"isobject": "^3.0.0"
@@ -10483,7 +10483,7 @@
"object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
"integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==",
"integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
"dev": true,
"requires": {
"isobject": "^3.0.1"
@@ -10565,7 +10565,7 @@
"is-wsl": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
"integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
"integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
"dev": true
}
}
@@ -10647,13 +10647,13 @@
"p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
"integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==",
"integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
"dev": true
},
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
},
"p-limit": {
@@ -10849,13 +10849,13 @@
"pascalcase": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
"integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==",
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
"dev": true
},
"path-dirname": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
"integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==",
"integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
"dev": true
},
"path-exists": {
@@ -11000,7 +11000,7 @@
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
"integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==",
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
"dev": true
},
"postcss": {
@@ -13224,7 +13224,7 @@
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
"dev": true
},
"querystringify": {
@@ -13583,7 +13583,7 @@
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
"integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==",
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
"dev": true
},
"repeat-element": {
@@ -13758,7 +13758,7 @@
"resolve-cwd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
"integrity": "sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==",
"integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
"dev": true,
"requires": {
"resolve-from": "^3.0.0"
@@ -13767,7 +13767,7 @@
"resolve-from": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
"integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
"dev": true
}
}
@@ -13781,7 +13781,7 @@
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
"integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==",
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
"dev": true
},
"resolve-url-loader": {
@@ -13840,7 +13840,7 @@
"retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
"integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
"dev": true
},
"reusify": {
@@ -13935,7 +13935,7 @@
"safe-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"dev": true,
"requires": {
"ret": "~0.1.10"
@@ -14313,7 +14313,7 @@
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
@@ -14457,7 +14457,7 @@
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
"integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
"dev": true,
"requires": {
"is-descriptor": "^0.1.0"
@@ -14466,7 +14466,7 @@
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
@@ -14475,7 +14475,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"source-map": {
@@ -14513,7 +14513,7 @@
"define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
"integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
"integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
"dev": true,
"requires": {
"is-descriptor": "^1.0.0"
@@ -14562,7 +14562,7 @@
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "^1.1.5"
@@ -14948,7 +14948,7 @@
"static-extend": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
"integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==",
"integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
"dev": true,
"requires": {
"define-property": "^0.2.5",
@@ -14958,7 +14958,7 @@
"define-property": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
"integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
"dev": true,
"requires": {
"is-descriptor": "^0.1.0"
@@ -15071,7 +15071,7 @@
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
"strip-final-newline": {
@@ -15354,7 +15354,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"semver": {
@@ -15674,7 +15674,7 @@
"to-object-path": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
"integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==",
"integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
"dev": true,
"requires": {
"kind-of": "^3.0.2"
@@ -15683,7 +15683,7 @@
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": {
"is-buffer": "^1.1.5"
@@ -16036,7 +16036,7 @@
"uniq": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
"integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==",
"integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
"dev": true
},
"unique-filename": {
@@ -16096,7 +16096,7 @@
"unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
"integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==",
"integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
"dev": true,
"requires": {
"has-value": "^0.3.1",
@@ -16106,7 +16106,7 @@
"has-value": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
"integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
"integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
"dev": true,
"requires": {
"get-value": "^2.0.3",
@@ -16117,7 +16117,7 @@
"isobject": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
"integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
"dev": true,
"requires": {
"isarray": "1.0.0"
@@ -16128,7 +16128,7 @@
"has-values": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
"integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==",
"integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
"dev": true
},
"isarray": {
@@ -16167,13 +16167,13 @@
"urix": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
"integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==",
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
"dev": true
},
"url": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
"integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
"dev": true,
"requires": {
"punycode": "1.3.2",
@@ -16183,7 +16183,7 @@
"punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
"dev": true
}
}
@@ -16540,7 +16540,7 @@
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"anymatch": {
@@ -16556,7 +16556,7 @@
"normalize-path": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
"integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
"dev": true,
"requires": {
"remove-trailing-separator": "^1.0.1"
@@ -16591,7 +16591,7 @@
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"requires": {
"is-extendable": "^0.1.0"
@@ -16695,7 +16695,7 @@
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
"integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
"dev": true,
"requires": {
"is-glob": "^3.1.0",
@@ -16705,7 +16705,7 @@
"is-glob": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
"integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
"integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
"dev": true,
"requires": {
"is-extglob": "^2.1.0"
@@ -16725,7 +16725,7 @@
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"is-number": {
@@ -16818,7 +16818,7 @@
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
},
"readable-stream": {
@@ -16904,7 +16904,7 @@
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"

View File

@@ -13,6 +13,7 @@
"importHelpers": false,
"allowSyntheticDefaultImports": true,
"target": "es5",
"downlevelIteration": true,
"typeRoots": [
"node_modules/@types"
],