Merge branch 'feature/1407-Checkout' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into feature/1407-Checkout

This commit is contained in:
Nino Righi
2021-02-25 16:21:42 +01:00
48 changed files with 515 additions and 57 deletions

View File

@@ -1856,6 +1856,46 @@
}
}
}
},
"@ui/spinner": {
"projectType": "library",
"root": "apps/ui/spinner",
"sourceRoot": "apps/ui/spinner/src",
"prefix": "ui",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"tsConfig": "apps/ui/spinner/tsconfig.lib.json",
"project": "apps/ui/spinner/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "apps/ui/spinner/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "apps/ui/spinner/src/test.ts",
"tsConfig": "apps/ui/spinner/tsconfig.spec.json",
"karmaConfig": "apps/ui/spinner/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"apps/ui/spinner/tsconfig.lib.json",
"apps/ui/spinner/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "sales"

View File

@@ -110,11 +110,17 @@
{{ item?.unitPrice?.value?.value | currency: item?.unitPrice?.value?.currency:'code' }}
</div>
<div class="product-quantity">
<page-quantity-control [ngModel]="item?.quantity" (ngModelChange)="updateItemQuantity(item, $event)"></page-quantity-control>
<page-quantity-control
[ngModel]="item?.quantity"
(ngModelChange)="updateItemQuantity(item, $event)"
[showSpinner]="showQuantityControlSpinnerItemId === item.id"
></page-quantity-control>
</div>
<div>
<button class="cta-edit" (click)="changeItem(item)">
Ändern
<button class="cta-edit" (click)="changeItem(item)" [disabled]="showChangeButtonSpinnerItemId">
<ui-spinner [show]="showChangeButtonSpinnerItemId === item.id">
Ändern
</ui-spinner>
</button>
</div>
</div>
@@ -133,8 +139,10 @@
</strong>
<span class="shipping-cost-info">ohne Versandkosten</span>
</div>
<button class="cta-order" (click)="order()">
Bestellen
<button class="cta-order" (click)="order()" [disabled]="showOrderButtonSpinner">
<ui-spinner [show]="showOrderButtonSpinner">
Bestellen
</ui-spinner>
</button>
</div>
</div>

View File

@@ -1,4 +1,4 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { Router } from '@angular/router';
import { ApplicationService } from '@core/application';
import { AvailabilityService } from '@domain/availability';
@@ -64,6 +64,10 @@ export class CheckoutReviewComponent {
switchMap((processId) => this.domainCheckoutService.getCustomerFeatures({ processId }))
);
showQuantityControlSpinnerItemId: number;
showOrderButtonSpinner: boolean;
showChangeButtonSpinnerItemId: number;
constructor(
private domainCheckoutService: DomainCheckoutService,
private applicationService: ApplicationService,
@@ -71,10 +75,12 @@ export class CheckoutReviewComponent {
private search: SearchService,
private uiModal: UiModalService,
private sso: SsoService,
private router: Router
private router: Router,
private cdr: ChangeDetectorRef
) {}
async changeItem(shoppingCartItem: ShoppingCartItemDTO) {
this.showChangeButtonSpinnerItemId = shoppingCartItem.id;
const item = await this.search
.SearchSearch({
input: { qs: shoppingCartItem.product.ean },
@@ -177,6 +183,9 @@ export class CheckoutReviewComponent {
break;
}
this.showChangeButtonSpinnerItemId = undefined;
this.cdr.markForCheck();
this.uiModal.open({
content: PurchasingOptionsModalComponent,
data: {
@@ -191,6 +200,7 @@ export class CheckoutReviewComponent {
}
async updateItemQuantity(shoppingCartItem: ShoppingCartItemDTO, quantity: number) {
this.showQuantityControlSpinnerItemId = shoppingCartItem.id;
const orderType = shoppingCartItem?.features?.orderType;
let availability: AvailabilityDTO;
@@ -239,15 +249,17 @@ export class CheckoutReviewComponent {
} else {
// TODO: Set Prev Quantity
}
this.showQuantityControlSpinnerItemId = undefined;
}
order() {
// TODO: Check if Customer is Set
// => If not navigate to customer search
this.showOrderButtonSpinner = true;
this.domainCheckoutService.completeCheckout({ processId: this.applicationService.activatedProcessId }).subscribe(() => {
this.applicationService.removeProcess(this.applicationService.activatedProcessId);
this.applicationService.createProcess();
this.showOrderButtonSpinner = false;
this.router.navigate(['/cart', 'summary']);
});
}

View File

@@ -8,6 +8,7 @@ import { CheckoutQuantityControlModule } from '../shared/quantity-control/quanti
import { ProductImageModule } from 'apps/cdn/product-image/src/public-api';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { UiSpinnerModule } from 'apps/ui/spinner/src/lib/ui-spinner.module';
@NgModule({
imports: [
@@ -18,6 +19,7 @@ import { FormsModule } from '@angular/forms';
CheckoutQuantityControlModule,
ProductImageModule,
FormsModule,
UiSpinnerModule,
],
exports: [CheckoutReviewComponent],
declarations: [CheckoutReviewComponent],

View File

@@ -1,14 +1,42 @@
<div class="card" *ngIf="orderData$ | async; let orderData">
<div>
<ui-icon class="check-icon" icon="check" size="36px"></ui-icon>
</div>
<h1 class="order-header">Bestellbestätigung</h1>
<p class="order-info">
Nachfolgend erhalten Sie die Übersicht Ihrer Bestellung.
Nachfolgend erhalten Sie <br />
die Übersicht Ihrer Bestellung.
</p>
<div class="cta-print-wrapper">
<div class="row">
<div class="order-customer">
{{ orderData?.buyer | buyerName }}
</div>
<div class="grow"></div>
<button class="cta-print">Drucken</button>
</div>
<div class="row">
<div class="order-customer"></div>
<div class="grow"></div>
<div class="sub-row">
<span>Belegnummer</span>
<strong>{{ orderData.orderNumber }}</strong>
</div>
<div class="sub-row between">
<span>Zielfiliale</span>
<strong>{{ orderData.targetBranch.name }}</strong>
</div>
</div>
<div class="row">
<div class="sub-row">
<span>Bestelldatum</span>
<strong>{{ orderData.orderDate | date }}</strong>
</div>
<div class="sub-row between">
<span>Adresse</span>
<strong>{{ orderData.targetBranch | branchAddress }}</strong>
</div>
</div>
<hr />
</div>

View File

@@ -2,8 +2,48 @@
@apply block box-border;
}
.cta-print-wrapper {
.check-icon {
@apply mx-auto text-green-700 pt-8;
width: 36px;
}
.card {
@apply bg-white rounded-card shadow-card;
}
.order-header {
@apply text-center text-3xl my-2 mb-2;
}
.order-info {
@apply text-center text-lg my-0 mb-2;
}
.cta-print {
@apply bg-transparent text-brand font-bold text-xl outline-none border-none;
}
.order-customer {
@apply font-bold text-2xl;
}
.grow {
@apply flex-grow;
}
.row {
@apply flex flex-row items-center mx-8 my-4;
}
.sub-row {
@apply flex flex-row flex-grow items-center w-1/2;
}
.between {
@apply justify-between;
}
hr {
height: 2px;
@apply bg-disabled-customer;
}

View File

@@ -2,9 +2,11 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CheckoutSummaryComponent } from './checkout-summary.component';
import { UiIconModule } from '@ui/icon';
import { PageCheckoutPipeModule } from '../pipes/page-checkout-pipe.module';
@NgModule({
imports: [CommonModule],
imports: [CommonModule, UiIconModule, PageCheckoutPipeModule],
exports: [CheckoutSummaryComponent],
declarations: [CheckoutSummaryComponent],
})

View File

@@ -1,8 +1,8 @@
.option-icon {
margin-top: -5px;
width: 80px;
margin-top: -12px;
width: 70px;
}
h4 {
margin-top: -10px;
margin-top: -2px;
}

View File

@@ -7,9 +7,11 @@
<span class="price"
>{{ item.catalogAvailability?.price?.value?.value | currency: ' ' }} {{ item.catalogAvailability?.price?.value?.currency }}</span
>
<div class="grow"></div>
<span class="delivery">Versandkostenfrei</span>
<span class="date">Versanddatum <strong>27.02.21</strong></span>
<div class="grow"></div>
<div>
<button type="button" class="select-option" (click)="select()">
Auswählen

View File

@@ -5,7 +5,7 @@
.option-icon {
@apply text-ucla-blue mx-auto;
width: 50px;
width: 40px;
}
h4 {

View File

@@ -43,6 +43,7 @@
</div>
<div class="quantity">
<page-quantity-control
[showSpinner]="purchasingOptionsModalStore.selectFetchingAvailability | async"
[ngModel]="quantity$ | async"
(ngModelChange)="purchasingOptionsModalStore.setQuantity($event)"
></page-quantity-control>
@@ -58,12 +59,20 @@
</div>
</div>
<div class="actions" *ngIf="option$ | async; let option">
<button class="cta-continue-shopping" [disabled]="(canAdd$ | async) === false" (click)="continue(true)">Weiter einkaufen</button>
<button class="cta-continue-shopping" [disabled]="(canAdd$ | async) === false" (click)="continue(true)">
<ui-spinner [show]="activeSpinner && activeSpinner === 'continue-shopping'">
Weiter einkaufen
</ui-spinner>
</button>
<button *ngIf="option === 'take-away'" class="cta-continue" [disabled]="(canAdd$ | async) === false" (click)="continue()">
Reservieren
<ui-spinner [show]="activeSpinner && activeSpinner === 'continue'">
Reservieren
</ui-spinner>
</button>
<button *ngIf="option !== 'take-away'" class="cta-continue" [disabled]="(canAdd$ | async) === false" (click)="continue()">
Fortfahren
<ui-spinner [show]="activeSpinner && activeSpinner === 'continue'">
Fortfahren
</ui-spinner>
</button>
</div>
</ng-container>

View File

@@ -11,7 +11,7 @@
}
.options-wrapper {
@apply flex flex-row justify-evenly items-stretch;
@apply flex flex-row justify-evenly items-stretch mt-2;
}
.option-product-summary {
@@ -72,6 +72,10 @@ img.thumbnail {
.cta-continue-shopping {
@apply text-brand border-2 border-solid border-brand bg-white font-bold text-lg px-4 py-2 rounded-full;
::ng-deep.spin {
@apply text-brand;
}
}
.cta-continue {

View File

@@ -4,7 +4,7 @@ import { ApplicationService } from '@core/application';
import { DomainCheckoutService } from '@domain/checkout';
import { AddToShoppingCartDTO } from '@swagger/checkout';
import { UiModalRef } from '@ui/modal';
import { first, map, mergeMap } from 'rxjs/operators';
import { delay, first, map, mergeMap } from 'rxjs/operators';
import { PurchasingOptionsModalData } from './purchasing-options-modal.data';
import { PurchasingOptionsModalStore } from './purchasing-options-modal.store';
@@ -34,6 +34,8 @@ export class PurchasingOptionsModalComponent {
readonly branch$ = this.purchasingOptionsModalStore.selectBranch;
activeSpinner: string;
constructor(
public modalRef: UiModalRef<any, PurchasingOptionsModalData>,
public purchasingOptionsModalStore: PurchasingOptionsModalStore,
@@ -50,6 +52,8 @@ export class PurchasingOptionsModalComponent {
}
async continue(navigate: boolean = false) {
this.activeSpinner = navigate ? 'continue-shopping' : 'continue';
try {
const processId = await this.purchasingOptionsModalStore.selectProcessId.pipe(first()).toPromise();
const item = await this.item$.pipe(first()).toPromise();
@@ -120,5 +124,6 @@ export class PurchasingOptionsModalComponent {
} catch (error) {
console.log('PurchasingOptionsModalComponent.continue', error);
}
this.activeSpinner = undefined;
}
}

View File

@@ -18,6 +18,7 @@ import { PickUpDropdownComponent } from './pick-up-option/pick-up-dropdown/pick-
import { PageCheckoutPipeModule } from '../../pipes/page-checkout-pipe.module';
import { ProductImageModule } from 'apps/cdn/product-image/src/public-api';
import { CheckoutQuantityControlModule } from '../../shared/quantity-control/quantity-control.module';
import { UiSpinnerModule } from 'apps/ui/spinner/src/lib/ui-spinner.module';
@NgModule({
imports: [
@@ -28,6 +29,7 @@ import { CheckoutQuantityControlModule } from '../../shared/quantity-control/qua
PageCheckoutPipeModule,
ProductImageModule,
CheckoutQuantityControlModule,
UiSpinnerModule,
],
exports: [PurchasingOptionsModalComponent],
declarations: [

View File

@@ -18,6 +18,7 @@ interface PurchasingOptionsModalState {
branch?: BranchDTO;
processId?: number;
availability?: AvailabilityDTO;
fetchingAvailability?: boolean;
availableOptions: PurchasingOptions[];
availableBranches: BranchDTO[];
quantity: number;
@@ -64,6 +65,8 @@ export class PurchasingOptionsModalStore extends ComponentStore<PurchasingOption
readonly selectFilterResult = this.select((s) => s.filterResult);
readonly selectFetchingAvailability = this.select((s) => s.fetchingAvailability);
readonly selectOlaAvailability = this.select(
(s): OLAAvailabilityDTO => ({
status: s.availability?.availabilityType,
@@ -249,6 +252,7 @@ export class PurchasingOptionsModalStore extends ComponentStore<PurchasingOption
let availability$: Observable<AvailabilityDTO> = NEVER;
if (!isNullOrUndefined(item) && quantity > 0 && isString(option)) {
this.patchState({ fetchingAvailability: true });
switch (option) {
case 'take-away':
if (!isNullOrUndefined(branch)) {
@@ -278,8 +282,13 @@ export class PurchasingOptionsModalStore extends ComponentStore<PurchasingOption
}
return availability$.pipe(
tapResponse(
(availability) => this.setAvailability(availability),
() => this.setAvailability(null)
(availability) => {
this.setAvailability(availability);
this.patchState({ fetchingAvailability: false });
},
() => {
this.setAvailability(null), this.patchState({ fetchingAvailability: false });
}
)
);
})

View File

@@ -0,0 +1,13 @@
import { Pipe, PipeTransform } from '@angular/core';
import { BranchDTO } from '@swagger/checkout';
@Pipe({
name: 'branchAddress',
})
export class BranchAddressPipe implements PipeTransform {
transform(branch: BranchDTO, ...args: any[]): any {
if (branch) {
return `${branch?.address?.street} ${branch?.address?.streetNumber}, ${branch?.address?.zipCode} ${branch?.address?.city}`;
}
}
}

View File

@@ -0,0 +1,19 @@
import { Pipe, PipeTransform } from '@angular/core';
import { BuyerDTO } from '@swagger/checkout';
@Pipe({
name: 'buyerName',
})
export class BuyerNamePipe implements PipeTransform {
transform(buyer: BuyerDTO, ...args: any[]): any {
if (buyer) {
const organisationParts = [buyer?.organisation?.name].filter((f) => !!f);
const customerParts = [buyer?.lastName, buyer?.firstName].filter((f) => !!f);
return [organisationParts.join(), customerParts.join(' ')].filter((f) => !!f).join(' - ');
}
return '';
}
}

View File

@@ -1,4 +1,6 @@
import { NgModule } from '@angular/core';
import { BranchAddressPipe } from './branch-address.pipe';
import { BuyerNamePipe } from './buyer-name.pipe';
import { PayerAddressPipe } from './payer-address.pipe';
import { PurchaseOptionIconPipe } from './purchase-option-icon.pipe';
import { PurchaseOptionNamePipe } from './purchase-option-name.pipe';
@@ -6,7 +8,23 @@ import { ShippingAddressPipe } from './shipping-address.pipe';
import { TrimPipe } from './trim.pipe';
@NgModule({
exports: [PayerAddressPipe, ShippingAddressPipe, TrimPipe, PurchaseOptionNamePipe, PurchaseOptionIconPipe],
declarations: [PayerAddressPipe, ShippingAddressPipe, TrimPipe, PurchaseOptionNamePipe, PurchaseOptionIconPipe],
exports: [
PayerAddressPipe,
ShippingAddressPipe,
TrimPipe,
PurchaseOptionNamePipe,
PurchaseOptionIconPipe,
BuyerNamePipe,
BranchAddressPipe,
],
declarations: [
PayerAddressPipe,
ShippingAddressPipe,
TrimPipe,
PurchaseOptionNamePipe,
PurchaseOptionIconPipe,
BuyerNamePipe,
BranchAddressPipe,
],
})
export class PageCheckoutPipeModule {}

View File

@@ -1,9 +1,11 @@
<div *ngIf="showDropdown" (click)="showDropdown = false" class="backdrop"></div>
<div class="quantity-control-wrapper" *ngIf="quantity">
<button class="current-quantity" type="button" (click)="showDropdown = true" *ngIf="!customInput">
{{ quantity }}
<ui-icon class="r90deg" size="14px" icon="arrow_head"></ui-icon>
</button>
<ui-spinner [show]="showSpinner">
<button class="current-quantity" type="button" (click)="showDropdown = true" *ngIf="!customInput">
{{ quantity }}
<ui-icon class="r90deg" size="14px" icon="arrow_head"></ui-icon>
</button>
</ui-spinner>
<input #quantity class="current-quantity" type="number" *ngIf="customInput" placeholder="..." />
<div class="quantity-list" *ngIf="showDropdown">
<button class="quantity-list-item del" type="button" (click)="close()">

View File

@@ -33,6 +33,9 @@ export class QuantityControlComponent implements ControlValueAccessor {
@Input()
disabled: boolean;
@Input()
showSpinner: boolean;
onChange = (_: number) => {};
onTouched = () => {};

View File

@@ -1,11 +1,12 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { UiIconModule } from '@ui/icon';
import { UiSpinnerModule } from 'apps/ui/spinner/src/lib/ui-spinner.module';
import { QuantityControlComponent } from './quantity-control.component';
@NgModule({
imports: [CommonModule, UiIconModule],
imports: [CommonModule, UiIconModule, UiSpinnerModule],
exports: [QuantityControlComponent],
declarations: [QuantityControlComponent],
})

View File

@@ -195,11 +195,10 @@
</div>
<div class="center sticky-bottom">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled" [ngSwitch]="control.enabled">
<ng-container *ngSwitchCase="true">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled">
<ui-spinner [show]="!control.enabled">
Speichern
</ng-container>
<ui-icon class="spin" icon="loading" size="18px" *ngSwitchCase="false"></ui-icon>
</ui-spinner>
</button>
</div>
</form>

View File

@@ -188,11 +188,10 @@
</div>
<div class="center sticky-bottom">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled" [ngSwitch]="control.enabled">
<ng-container *ngSwitchCase="true">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled">
<ui-spinner [show]="!control.enabled">
Speichern
</ng-container>
<ui-icon class="spin" icon="loading" size="18px" *ngSwitchCase="false"></ui-icon>
</ui-spinner>
</button>
</div>
</form>

View File

@@ -195,11 +195,10 @@
</div>
<div class="center sticky-bottom">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled" [ngSwitch]="control.enabled">
<ng-container *ngSwitchCase="true">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled">
<ui-spinner [show]="!control.enabled">
Speichern
</ng-container>
<ui-icon class="spin" icon="loading" size="18px" *ngSwitchCase="false"></ui-icon>
</ui-spinner>
</button>
</div>
</form>

View File

@@ -192,11 +192,10 @@
</div>
<div class="center sticky-bottom">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled" [ngSwitch]="control.enabled">
<ng-container *ngSwitchCase="true">
<button class="create-customer-submit" type="submit" [disabled]="control.invalid || control.disabled">
<ui-spinner [show]="!control.enabled">
Speichern
</ng-container>
<ui-icon class="spin" icon="loading" size="18px" *ngSwitchCase="false"></ui-icon>
</ui-spinner>
</button>
</div>
</form>

View File

@@ -78,3 +78,7 @@ page-customer-type-selector {
.organisation-header {
}
::ng-deep.spin {
@apply text-white;
}

View File

@@ -15,6 +15,7 @@ import { AddressSelectionModalModule } from '../modals/address-selection-modal/a
import { CantAddCustomerToCartModalModule } from '../modals/cant-add-customer-to-cart-modal/cant-add-customer-to-cart.module';
import { UiIconModule } from '@ui/icon';
import { UiCheckboxModule } from '@ui/checkbox';
import { UiSpinnerModule } from 'apps/ui/spinner/src/lib/ui-spinner.module';
@NgModule({
imports: [
@@ -29,6 +30,7 @@ import { UiCheckboxModule } from '@ui/checkbox';
AddressSelectionModalModule,
CantAddCustomerToCartModalModule,
UiCheckboxModule,
UiSpinnerModule,
],
exports: [CustomerCreateBranchComponent, CustomerCreateGuestComponent, CustomerCreateOnlineComponent, CustomerCreateB2BComponent],
declarations: [

View File

@@ -129,12 +129,16 @@
</div>
<div class="card-customer-footer">
<button *ngIf="cartExists$ | async; else cartEmpty" class="cta-to-cart" (click)="continue()">
Weiter zum Warenkorb
<button *ngIf="cartExists$ | async; else cartEmpty" class="cta-to-cart" (click)="continue()" [disabled]="showSpinner">
<ui-spinner [show]="showSpinner">
Weiter zum Warenkorb
</ui-spinner>
</button>
<ng-template #cartEmpty>
<button class="cta-to-cart" (click)="continue()">
Weiter zur Artikelsuche
<button class="cta-to-cart" (click)="continue()" [disabled]="showSpinner">
<ui-spinner [show]="showSpinner">
Weiter zur Artikelsuche
</ui-spinner>
</button>
</ng-template>
</div>

View File

@@ -42,6 +42,7 @@ export class CustomerDetailsComponent implements OnInit {
isWebshopOrGuest$: Observable<boolean>;
cartExists$: Observable<boolean>;
hasCustomerCard$: Observable<boolean>;
showSpinner: boolean;
private currentBreadcrumb: Breadcrumb;
@@ -152,6 +153,7 @@ export class CustomerDetailsComponent implements OnInit {
}
async continue() {
this.showSpinner = true;
const customer = await this.customer$.pipe(first()).toPromise();
// Check if customer can be added to the checkout
@@ -170,6 +172,7 @@ export class CustomerDetailsComponent implements OnInit {
upgradeableTo: canBeExtendedTo,
} as CantAddCustomerToCartData,
});
this.showSpinner = false;
return;
} else {
const updateDestination = await this.checkoutService
@@ -190,6 +193,7 @@ export class CustomerDetailsComponent implements OnInit {
} as CantAddCustomerToCartData,
});
this.showSpinner = false;
return;
}
}
@@ -251,6 +255,8 @@ export class CustomerDetailsComponent implements OnInit {
} else {
this.router.navigate(['/product/search']);
}
this.showSpinner = false;
}
getCusomterFeatures(custoemr: CustomerDTO): { [key: string]: string } {

View File

@@ -27,6 +27,7 @@ import { CardTemplateComponent } from './shared/card-template/card-template.comp
import { CustomerOrdersComponent } from './customer-orders/customer-orders.component';
import { UiCommonModule } from '@ui/common';
import { CustomerHistoryComponent } from './customer-history/customer-history.component';
import { UiSpinnerModule } from 'apps/ui/spinner/src/lib/ui-spinner.module';
@NgModule({
imports: [
CommonModule,
@@ -40,6 +41,7 @@ import { CustomerHistoryComponent } from './customer-history/customer-history.co
FormsModule,
UiRadioModule,
UiCommonModule,
UiSpinnerModule,
],
exports: [CustomerDetailsComponent],
declarations: [

View File

@@ -23,6 +23,8 @@ export class BranchesAvalabilityOverviewComponent implements OnInit, OnDestroy {
branchInfos: BranchInfoView[] = [];
filteredBranchInfos: BranchInfoView[] = [];
userBranch: BranchDTO;
@Output() loaded = new EventEmitter<void>();
@Output() destroymodal: EventEmitter<boolean> = new EventEmitter();
destroy$ = new Subject();
@@ -76,6 +78,7 @@ export class BranchesAvalabilityOverviewComponent implements OnInit, OnDestroy {
.subscribe((t) => {
this.branchInfos = t.filter((b) => b && b.load);
this.filteredBranchInfos = this.loadDefaultBranches();
this.loaded.emit();
});
}

View File

@@ -218,9 +218,9 @@
</div>
</ng-template>
<div class="actions align-right" [ngClass]="{ 'action-partly-loaded': !fullyLoaded }">
<app-button (action)="openBranchesAvailabilityModal()" *ngIf="product.formatIcon !== 'EB' && product.formatIcon !== 'DL'"
>weitere Verfügbarkeiten</app-button
>
<app-button (action)="openBranchesAvailabilityModal()" *ngIf="product.formatIcon !== 'EB' && product.formatIcon !== 'DL'">
weitere Verfügbarkeiten
</app-button>
<app-button
[primary]="true"
[load]="true"
@@ -281,6 +281,7 @@
<ng-container *ngIf="item && loadBranchesInfoComponent">
<app-branches-avalability-overview
(loaded)="branchesAvailabilityInfo.openDialog()"
(destroymodal)="destroyAvailabilityModal($event)"
[item]="item"
#branchesAvailabilityInfo

View File

@@ -512,7 +512,6 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
openBranchesAvailabilityModal() {
this.loadBranchesInfoComponent = true;
this.detectChanges();
this.branchesAvailabilityInfo.openDialog();
}
destroyAvailabilityModal() {

25
apps/ui/spinner/README.md Normal file
View File

@@ -0,0 +1,25 @@
# Spinner
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.2.
## Code scaffolding
Run `ng generate component component-name --project spinner` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project spinner`.
> Note: Don't forget to add `--project spinner` or else it will be added to the default project in your `angular.json` file.
## Build
Run `ng build spinner` to build the project. The build artifacts will be stored in the `dist/` directory.
## Publishing
After building your library with `ng build spinner`, go to the dist folder `cd dist/spinner` and run `npm publish`.
## Running unit tests
Run `ng test spinner` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@@ -0,0 +1,32 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../../../coverage/ui/spinner'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true,
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
});
};

View File

@@ -0,0 +1,7 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../../dist/ui/spinner",
"lib": {
"entryFile": "src/public-api.ts"
}
}

View File

@@ -0,0 +1,11 @@
{
"name": "@ui/spinner",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^10.1.2",
"@angular/core": "^10.1.2"
},
"dependencies": {
"tslib": "^2.0.0"
}
}

View File

@@ -0,0 +1,5 @@
<!-- <ng-container [ngSwitch]="show"> -->
<ui-icon *ngIf="show" class="spin" icon="spinner" size="28px"></ui-icon>
<span class="content" [class.invisible]="show">
<ng-content></ng-content>
</span>

View File

@@ -0,0 +1,16 @@
:host {
@apply flex items-center relative;
}
.content {
@apply w-full;
}
.spin {
@apply animate-spin absolute;
left: calc(50% - 14px);
}
.invisible {
visibility: hidden;
}

View File

@@ -0,0 +1,15 @@
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'ui-spinner',
templateUrl: 'ui-spinner.component.html',
styleUrls: ['./ui-spinner.component.scss'],
})
export class SpinnerComponent implements OnInit {
@Input()
show: boolean;
constructor() {}
ngOnInit(): void {}
}

View File

@@ -0,0 +1,11 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { UiIconModule } from '@ui/icon';
import { SpinnerComponent } from './ui-spinner.component';
@NgModule({
declarations: [SpinnerComponent],
imports: [UiIconModule, CommonModule],
exports: [SpinnerComponent],
})
export class UiSpinnerModule {}

View File

@@ -0,0 +1,4 @@
/*
* Public API Surface of spinner
*/
export * from './lib';

View File

@@ -0,0 +1,24 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone';
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(
path: string,
deep?: boolean,
filter?: RegExp
): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View File

@@ -0,0 +1,25 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "../../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"lib": [
"dom",
"es2018"
]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

View File

@@ -0,0 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"enableIvy": false
}
}

View File

@@ -0,0 +1,17 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "../../../out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@@ -0,0 +1,17 @@
{
"extends": "../../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"ui",
"camelCase"
],
"component-selector": [
true,
"element",
"ui",
"kebab-case"
]
}
}

View File

@@ -176,6 +176,9 @@
],
"@cdn/product-image": [
"apps/cdn/product-image/cdn-product-image/src/public-api.ts"
],
"@ui/spinner": [
"apps/ui/spinner/src/public-api.ts"
]
}
}