Merge develop

This commit is contained in:
Eraldo Hasanaj
2020-05-27 14:13:24 +02:00
23 changed files with 392 additions and 94 deletions

5
.npmrc
View File

@@ -1,7 +1,7 @@
registry=https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/
always-auth=true
; Treat this auth token like a password. Do not share it with anyone, including Microsoft support. This token expires on or before 24.05.2020.
; Treat this auth token like a password. Do not share it with anyone, including Microsoft support. This token expires on or before 25.08.2020.
; begin auth token
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/:username=hugendubel
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/:_password=M2JkaDdwNjIzbWVoZGlmeDU3N2Ficjc3M252NXBkaWg1M2VtaW94dXp5amwyejNkaW5yYQ==
@@ -9,4 +9,5 @@ always-auth=true
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/:username=hugendubel
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/:_password=M2JkaDdwNjIzbWVoZGlmeDU3N2Ficjc3M252NXBkaWg1M2VtaW94dXp5amwyejNkaW5yYQ==
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/:email=npm requires email to be set but doesn't use the value
; end auth token
; end auth token

View File

@@ -14,12 +14,14 @@ export class ProductMapping {
let price = 0;
let priceDto: PriceDTO;
let ssctext = '';
let ssc = '';
let sscText = '';
let storeStatusCode = 0;
if (!!item.catalogAvailability) {
priceDto = item.catalogAvailability.price;
ssctext = item.catalogAvailability.sscText;
ssc = item.catalogAvailability.ssc;
sscText = item.catalogAvailability.sscText;
storeStatusCode = item.catalogAvailability.status;
}
@@ -63,7 +65,8 @@ export class ProductMapping {
imageId: item.imageId,
edition: item.product.edition,
volume: item.product.volume,
sscText: ssctext && ssctext.length > 28 ? ssctext.substr(0, 28) + '...' : ssctext,
ssc,
sscText,
storeStatusCode: storeStatusCode,
};
}

View File

@@ -22,6 +22,7 @@ export interface Product {
location: string;
ean: string;
imageId: string;
ssc: string,
sscText: string;
storeStatusCode: number;
}

View File

@@ -9,13 +9,20 @@
</div>
<div class="content-container">
<div class="author align-left">
<ng-container *ngFor="let author of authors; let i = index; let last = last">
<span [id]="'author' + i" (click)="filterByAuthor(author)">{{ author }}</span>
<ng-container
*ngFor="let author of authors; let i = index; let last = last"
>
<span [id]="'author' + i" (click)="filterByAuthor(author)">{{
author
}}</span>
<span *ngIf="!last">{{ '; ' }}</span>
</ng-container>
</div>
<div class="title-price">
<div class="title align-left" [ngClass]="{ 'title-grid': product.recommandation }">
<div
class="title align-left"
[ngClass]="{ 'title-grid': product.recommandation }"
>
<div class="rec-icon-container" *ngIf="product.recommandation">
<lib-icon name="Empfehlungen_Icon"></lib-icon>
</div>
@@ -32,30 +39,45 @@
<div class="type-stock">
<div class="type align-left">
<div class="type-icon-container align-left">
<lib-icon *ngIf="!!product.typeIcon && product.typeIcon != '--'" name="Icon_{{ product.typeIcon }}"></lib-icon>
<lib-icon
*ngIf="!!product.typeIcon && product.typeIcon != '--'"
name="Icon_{{ product.typeIcon }}"
></lib-icon>
</div>
<div class="type-text align-left">
<span>{{ product.type }}</span>
</div>
</div>
<div class="stock-container align-right">
<div class="available-stock" [ngClass]="{ 'no-quantity-container': product.itemsInStock === 0 }">
<div class="stock-icon-wraper" *ngIf="product.itemsInStock && product.itemsInStock > 0">
<div
class="available-stock"
[ngClass]="{ 'no-quantity-container': product.itemsInStock === 0 }"
>
<div
class="stock-icon-wraper"
*ngIf="product.itemsInStock && product.itemsInStock > 0"
>
<lib-icon
class="stock-icon"
name="{{ product.recommandation ? 'Icon_House_recommended' : 'Icon_House' }}"
name="{{
product.recommandation ? 'Icon_House_recommended' : 'Icon_House'
}}"
height="19px"
width="16px"
></lib-icon>
</div>
<div class="stock" *ngIf="product.itemsInStock && product.itemsInStock > 0">
<span *ngIf="product.itemsInStock">{{ product.itemsInStock }}x</span>
<div
class="stock"
*ngIf="product.itemsInStock && product.itemsInStock > 0"
>
<span *ngIf="product.itemsInStock"
>{{ product.itemsInStock }}x</span
>
<span *ngIf="!product.itemsInStock">0x</span>
</div>
</div>
<div class="store-availability">
<div class="availability-image">
<!-- <lib-icon name="Package_Icon_blue" height="18px" *ngIf="product.typeIcon !== 'EB' && product.storeStatusCode > 1"></lib-icon> -->
<lib-icon
name="download_product"
mr="3px"
@@ -80,16 +102,31 @@
</div>
<div class="volume-edition">
<span
>{{ product.edition }}<span *ngIf="product.edition && product.volume">|</span>{{ product.volume ? product.volume : '' }}
<span *ngIf="(product.edition || product.volume) && product.publicationDate">|</span> {{ publicationDate }}</span>
>{{ product.edition
}}<span *ngIf="product.edition && product.volume">|</span
>{{ product.volume ? product.volume : '' }}
<span
*ngIf="
(product.edition || product.volume) && product.publicationDate
"
>|</span
>
{{ publicationDate }}</span
>
<span class="order">{{ product.category }}</span>
</div>
</div>
<div class="avalability-text">
<span *ngIf="product.typeIcon !== 'EB' && product.typeIcon !== 'DL'">{{
product.storeStatusCode === 999 ? 'Lieferbar' : product.sscText
}}</span>
<span *ngIf="product.typeIcon === 'EB' || product.typeIcon === 'DL'">Download</span>
<div *ngIf="product.typeIcon !== 'EB' && product.typeIcon !== 'DL'">
<span *ngIf="product.ssc">{{ product.ssc }}</span
><span *ngIf="product.ssc && product.sscText"> - </span>
<span *ngIf="product.sscText">{{
product.storeStatusCode === 999 ? 'Lieferbar' : product.sscText
}}</span>
</div>
<span *ngIf="product.typeIcon === 'EB' || product.typeIcon === 'DL'"
>Download</span
>
</div>
</div>
</div>

View File

@@ -62,7 +62,7 @@
&.multi-line {
font-size: 22px;
transition: font-size .05s ease-out;
transition: font-size 0.05s ease-out;
margin-bottom: 14px;
}
}
@@ -95,13 +95,12 @@
.avalability-text {
font-family: 'Open Sans';
font-size: 18px;
font-size: 16px;
font-weight: bold;
line-height: 21px;
color: #000000;
word-break: break-word;
max-width: 220px;
text-align: end;
margin-top: -1px;
}
.type {

View File

@@ -7,15 +7,38 @@
(scroll)="scrollHandler($event)"
>
<div class="feature-icons" *ngIf="showFeatures">
<lib-icon name="subscription_tag" alt="subscription icon" type="png" height="48px" *ngIf="isSubscription"></lib-icon>
<lib-icon name="gift_tag" alt="gift icon" type="png" height="48px" *ngIf="isGiftable"></lib-icon>
<lib-icon name="recommendation_tag" alt="recommendation icon" type="png" height="48px" *ngIf="isRecommendation"></lib-icon>
<lib-icon
name="subscription_tag"
alt="subscription icon"
type="png"
height="48px"
*ngIf="isSubscription"
></lib-icon>
<lib-icon
name="gift_tag"
alt="gift icon"
type="png"
height="48px"
*ngIf="isGiftable"
></lib-icon>
<lib-icon
name="recommendation_tag"
alt="recommendation icon"
type="png"
height="48px"
*ngIf="isRecommendation"
></lib-icon>
</div>
<div [@shrinkTitle]="!expanded" (click)="expand()">{{ product.title }}</div>
<div class="general-details" *ngIf="expanded">
<div class="product-image-container">
<img [src]="product.imageId | bookImageUrl: 469:575 | async" class="product-image" alt="book image" (click)="openGallery()" />
<img
[src]="product.imageId | bookImageUrl: 469:575 | async"
class="product-image"
alt="book image"
(click)="openGallery()"
/>
<div class="img-magnifying-glass" (click)="openGallery()">
<lib-icon name="magnifying-glass" width="27px"></lib-icon>
</div>
@@ -26,7 +49,10 @@
<div class="autor standart-text align-left">
<span>{{ product.author }}</span>
</div>
<div class="print align-right" [ngClass]="{ 'print-btn-move-down': showFeatures }">
<div
class="print align-right"
[ngClass]="{ 'print-btn-move-down': showFeatures }"
>
<span (click)="printerSelect()">Drucken</span>
</div>
</div>
@@ -38,14 +64,22 @@
<div class="align-left">
<div class="type">
<div>
<lib-icon name="Icon_{{ product.formatIcon }}" mt="4px" height="17px"></lib-icon>
<lib-icon
name="Icon_{{ product.formatIcon }}"
mt="4px"
height="17px"
></lib-icon>
</div>
<div>
<span>{{ product.format }}</span>
</div>
</div>
<div class="volume-edition">
<span>{{ product.volume }} <span *ngIf="product.volume && product.edition">|</span> {{ product.edition }}</span>
<span
>{{ product.volume }}
<span *ngIf="product.volume && product.edition">|</span>
{{ product.edition }}</span
>
</div>
<div class="publication">
<span>{{ product.publicationDate }}</span>
@@ -53,7 +87,9 @@
</div>
<div>
<div class="price align-right">
<span>{{ product.price | bookPrice }} {{ product.currency }}</span>
<span
>{{ product.price | bookPrice }} {{ product.currency }}</span
>
</div>
<div class="promo-points align-right">
<span>{{ product.promoPoints }} Lesepunkte</span>
@@ -81,15 +117,25 @@
<app-stock-info-loading></app-stock-info-loading>
</div>
</div>
<div class="e-book-download align-right" *ngIf="product.formatIcon === 'EB' || product.formatIcon === 'DL'">
<div
class="e-book-download align-right"
*ngIf="product.formatIcon === 'EB' || product.formatIcon === 'DL'"
>
<div class="download-icon">
<lib-icon name="download_product_grey" mt="4px" height="17px"></lib-icon>
<lib-icon
name="download_product_grey"
mt="4px"
height="17px"
></lib-icon>
</div>
<div class="download-text">
<span>Download</span>
</div>
</div>
<div class="category align-right" *ngIf="product.formatIcon === 'EB' || product.formatIcon === 'DL'">
<div
class="category align-right"
*ngIf="product.formatIcon === 'EB' || product.formatIcon === 'DL'"
>
<span>{{ product.assortment }}</span>
</div>
</div>
@@ -98,8 +144,13 @@
<div class="lang-ean-age">
<div class="languages standart-text">
<span
>{{ product.genre.length > 20 ? product.genre.substring(0, 20) + '...' : product.genre }}
<span *ngIf="product.genre && product.locale">|</span> {{ product.locale }}</span
>{{
product.genre.length > 20
? product.genre.substring(0, 20) + '...'
: product.genre
}}
<span *ngIf="product.genre && product.locale">|</span>
{{ product.locale }}</span
>
</div>
<div class="ean standart-text">
@@ -111,29 +162,60 @@
</div>
<div class="avilability-status" *ngIf="!(showAvLoading | async)">
<div class="status-icons" *ngIf="!(isDownload | async)">
<div class="align-right ship-icon align-right" *ngIf="(shippingAvailable | async) && !(deliveryError$ |
async)">
<div
class="align-right ship-icon align-right"
*ngIf="(shippingAvailable | async) && !(deliveryError$ | async)"
>
<lib-icon name="Truck_Icon_grey" height="17px"></lib-icon>
</div>
<div class="align-right ship-icon align-right" *ngIf="(deliveryError$ | async)">
<lib-icon name="Icon_Truck_Questionmark" mt="-4px" height="22px"
tooltip="{{(deliveryError$ | async)}}" placement="top" delay="200"></lib-icon>
<div
class="align-right ship-icon align-right"
*ngIf="deliveryError$ | async"
>
<lib-icon
name="Icon_Truck_Questionmark"
mt="-4px"
height="22px"
tooltip="{{ deliveryError$ | async }}"
placement="top"
delay="200"
></lib-icon>
</div>
<div class="align-right send-icon" *ngIf="(storeAvailable | async) && !(storeError$ | async)">
<div
class="align-right send-icon"
*ngIf="(storeAvailable | async) && !(storeError$ | async)"
>
<lib-icon name="Package_Icon_grey" height="18px"></lib-icon>
</div>
<div class="align-right send-icon" *ngIf="(storeError$ | async)">
<lib-icon name="Icon_Pickup_Questionmark" mt="-4px" height="22px"
tooltip="{{(storeError$ | async)}}" placement="top" delay="200"></lib-icon>
<div class="align-right send-icon" *ngIf="storeError$ | async">
<lib-icon
name="Icon_Pickup_Questionmark"
mt="-4px"
height="22px"
tooltip="{{ storeError$ | async }}"
placement="top"
delay="200"
></lib-icon>
</div>
</div>
<div class="availability-status-text align-right">
<span>{{ availabilityStatusText }}</span>
<div
*ngIf="product.formatIcon !== 'EB' && product.formatIcon !== 'DL'"
class="availability-status-text align-right"
>
<span *ngIf="availabilityStatus">{{ availabilityStatus }}</span
><span *ngIf="availabilityStatus && availabilityStatus"> - </span>
<span *ngIf="availabilityStatusText">{{
availabilityStatusText
}}</span>
</div>
</div>
<div *ngIf="showAvLoading | async">
<app-availability-loading></app-availability-loading>
</div>
<ng-container
*ngIf="product.formatIcon !== 'EB' && product.formatIcon !== 'DL'"
>
<div *ngIf="showAvLoading | async">
<app-availability-loading></app-availability-loading>
</div>
</ng-container>
<div></div>
<div class="category align-right" *ngIf="!(isDownload | async)">
<span>{{ product.assortment }}</span>
@@ -142,7 +224,9 @@
<div
class="product-staus-info"
[ngClass]="{ 'partly-loaded': !fullyLoaded }"
*ngIf="(productReview$ | async)?.employeeReviews || (fullStars | async)"
*ngIf="
(productReview$ | async)?.employeeReviews || (fullStars | async)
"
>
<div class="stars-wrapper">
<ng-container *ngFor="let star of fullStars | async">
@@ -155,8 +239,14 @@
<lib-icon name="Star_empty" width="12px" type="png"></lib-icon>
</ng-container>
</div>
<div class="rating-status" (click)="ratingInfo()" *ngIf="productReview$ | async">
<span>{{ (productReview$ | async)?.employeeReviews }} Rezensionen</span>
<div
class="rating-status"
(click)="ratingInfo()"
*ngIf="productReview$ | async"
>
<span
>{{ (productReview$ | async)?.employeeReviews }} Rezensionen</span
>
</div>
</div>
<div></div>
@@ -165,13 +255,26 @@
</div>
<div class="separator" *ngIf="expanded"></div>
<div class="product-details" *ngIf="expanded">
<ng-container *ngIf="product.fullDescription && product.fullDescription.length > 0 && showNoDescription === false; else noDescription">
<ng-container
*ngIf="
product.fullDescription &&
product.fullDescription.length > 0 &&
showNoDescription === false;
else noDescription
"
>
<ng-container *ngIf="product.fullDescription.length > 100">
<div class="details" id="details-container" *ngIf="!moreBtn">
<span id="details-text">{{ product.fullDescription | descriptionText }}</span>
<span id="details-text">{{
product.fullDescription | descriptionText
}}</span>
<span class="more-btn" (click)="toggleMore('more')"
>Mehr
<lib-icon name="Arrow_Next-with-body" pl="8px" alt="more"></lib-icon>
<lib-icon
name="Arrow_Next-with-body"
pl="8px"
alt="more"
></lib-icon>
</span>
</div>
<div class="details-full" id="details-container" *ngIf="moreBtn">
@@ -183,7 +286,9 @@
</div>
</ng-container>
<ng-container *ngIf="product.fullDescription && product.fullDescription.length <= 100">
<ng-container
*ngIf="product.fullDescription && product.fullDescription.length <= 100"
>
<div class="details" id="details-container">
<span id="details-text" [innerHTML]="product.fullDescription"></span>
</div>
@@ -191,11 +296,18 @@
</ng-container>
<ng-template #noDescription>
<div class="details" id="details-container">
<span id="details-text">Für diesen Artikel ist keine Beschreibung verfügbar</span>
<span id="details-text"
>Für diesen Artikel ist keine Beschreibung verfügbar</span
>
</div>
</ng-template>
<div class="actions align-right" [ngClass]="{ 'action-partly-loaded': !fullyLoaded }">
<app-button (action)="openBranchesAvailabilityModal()" *ngIf="product.formatIcon !== 'EB' && product.formatIcon !== 'DL'"
<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
@@ -227,7 +339,10 @@
<app-product-details-loading></app-product-details-loading>
</div>
<ng-container *ngIf="productReview$">
<app-product-review #productReview [review]="productReview$ | async"></app-product-review>
<app-product-review
#productReview
[review]="productReview$ | async"
></app-product-review>
</ng-container>
<!-- <app-loading [text]="'Inhalte werden geladen'"></app-loading> -->
@@ -241,8 +356,12 @@
*ngIf="
item &&
product &&
(((storeAvLoaded === true && shippingAvLoaded === true) || downloadLoaded === true) &&
((takeNowAvailable | async) || (storeAvailable | async) || (shippingAvailable | async) || (downloadAvailable | async)))
((storeAvLoaded === true && shippingAvLoaded === true) ||
downloadLoaded === true) &&
((takeNowAvailable | async) ||
(storeAvailable | async) ||
(shippingAvailable | async) ||
(downloadAvailable | async))
"
>
<app-checkout
@@ -267,11 +386,24 @@
></app-branches-avalability-overview>
</ng-container>
<app-printer-selection #printModal (print)="print($event)"></app-printer-selection>
<app-printer-selection
#printModal
(print)="print($event)"
></app-printer-selection>
<div class="recommendations" [@shrinkSecondary]="!expanded" *ngIf="item && !loadingError">
<div
class="recommendations"
[@shrinkSecondary]="!expanded"
*ngIf="item && !loadingError"
>
<div class="header" *ngIf="expanded" (click)="expand()">
<lib-icon name="recommendation_tag" alt="recommendation icon" type="png" height="48px" class="recommendation-card-icon"></lib-icon>
<lib-icon
name="recommendation_tag"
alt="recommendation icon"
type="png"
height="48px"
class="recommendation-card-icon"
></lib-icon>
<span>Empfehlungen</span>
</div>

View File

@@ -338,7 +338,7 @@
.lang-ean-age-availability-status {
display: grid;
grid-template-columns: auto 173px;
grid-template-columns: auto 250px;
grid-gap: 5px;
.avilability-status {
@@ -352,9 +352,11 @@
}
.availability-status-text {
width: 173px;
font-size: 18px;
font-weight: bold;
line-height: 21px;
text-align: end;
margin-left: auto;
}
}
}
@@ -375,7 +377,7 @@
margin-right: 5px;
}
/*
/*
##Device = Big Desktops
*/
@media (min-width: 1281px) {
@@ -393,7 +395,7 @@
}
}
/*
/*
##Device = Laptops, Desktops, Ipad pro
*/
@media (min-width: 1025px) and (max-width: 1280px) {
@@ -411,7 +413,7 @@
}
}
/*
/*
##Device = Tablets, Ipads
*/
@media (min-width: 768px) and (max-width: 1024px) {
@@ -420,13 +422,13 @@
}
}
/*
/*
##Device = Low Resolution Tablets, Mobiles (Landscape)
*/
@media (min-width: 481px) and (max-width: 767px) {
}
/*
/*
##Device = Most of the Smartphones Mobiles (Portrait)
*/
@media (min-width: 320px) and (max-width: 480px) {

View File

@@ -68,6 +68,7 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
_halfStars = 0;
_emptyStars = 0;
loadBranchesInfoComponent = false;
availabilityStatus: string;
availabilityStatusText: string;
currentPickUpDate = '';
currentDeliveryDate = '';
@@ -632,7 +633,7 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
.getShippingAvailabilityWithCheck(item, ean, branch.id)
.pipe(takeUntil(this.destroy$))
.subscribe((response) => {
if ((response as { error: boolean; message: string; type: CheckoutType }).error) {
if ((response as { error: boolean; message: string; type: CheckoutType; }).error) {
this.downloadError = true;
this.downloadLoaded = true;
if (this.addToCartBtn) {
@@ -647,6 +648,7 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
if (successfulResponse) {
const preferredAvailability = successfulResponse.av.find((t) => t.preferred === 1 && t.supplier === 'DIG');
if (preferredAvailability) {
this.availabilityStatus = preferredAvailability.ssc;
this.availabilityStatusText = preferredAvailability.sscText;
if (preferredAvailability.price && preferredAvailability.price.value && preferredAvailability.price.value.value) {
this.downloadPrice = preferredAvailability.price.value.value;
@@ -684,7 +686,7 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
async loadAvailability(it: ItemDTO, ean: string): Promise<boolean> {
const availabilityObservables: Observable<
{ branchId: number; type: CheckoutType; av: AvailabilityDTO[] } | { error: boolean; message: string; type: CheckoutType }
{ branchId: number; type: CheckoutType; av: AvailabilityDTO[]; } | { error: boolean; message: string; type: CheckoutType; }
>[] = [];
const userBranchNumber = this.store.selectSnapshot(BranchSelectors.getUserBranch);
const branch = this.store.selectSnapshot(BranchSelectors.getBranchesIterable).find((t) => t.branchNumber === userBranchNumber);
@@ -713,7 +715,7 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
type: CheckoutType;
av: AvailabilityDTO[];
}
| { error: boolean; message: string; type: CheckoutType }
| { error: boolean; message: string; type: CheckoutType; }
) => {
if (
(response as {
@@ -751,6 +753,7 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
return;
}
if (item.type === CheckoutType.store) {
this.availabilityStatus = preferredAvailability.ssc;
this.availabilityStatusText = preferredAvailability.sscText;
this.currentPickUpDate = preferredAvailability.at
? this.datePipe.transform(new Date(preferredAvailability.at), 'dd.MM.yy')
@@ -790,6 +793,8 @@ export class ProductDetailsComponent implements OnInit, OnDestroy {
if (this.addToCartBtn) {
this.addToCartBtn.stopLoading();
}
this.cdrf.detectChanges();
});
return true;
}

View File

@@ -115,7 +115,7 @@ export class AddProductToRemissionDialogComponent implements OnInit, OnDestroy {
this.reasonError = false;
this.remissionHelper.addRemissionListItem(response);
this.modalService.close(this.id);
this.add.emit(this.product);
this.add.emit(response);
});
}
}

View File

@@ -29,6 +29,7 @@ export class RemissionListComponent implements OnInit, OnDestroy {
@Output() scroll = new EventEmitter<void>();
@Output() updateShippingDocument = new EventEmitter<void>();
@Select(RemissionSelectors.getRemissionProcess) remissionProcess$: Observable<RemissionProcess>;
@Select(RemissionSelectors.getRemissionActiveFilters) selectedFilters$: Observable<{ [key: string]: []; }>;
ds: RemissionListDataSource;
destroy$ = new Subject();
@@ -70,12 +71,31 @@ export class RemissionListComponent implements OnInit, OnDestroy {
});
this.subscribeToRefetchProducts();
this.subscribeToFetchLastProducts();
}
this.subscribeToResetCurrentPage();
this.subscribeToRefetchAllProducts();
};
ngOnDestroy() {
this.destroy$.next();
}
subscribeToResetCurrentPage() {
this.selectedFilters$.pipe(takeUntil(this.destroy$)).subscribe(() => this.resetPagesFetched());
};
private resetPagesFetched() {
this.page = 0;
this.isFullListLoaded = false;
this.isFullLoad = false;
}
subscribeToRefetchAllProducts() {
this.remissionHelper.refetchProducts$.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.refetchLoadedProducts(10);
});
}
subscribeToFetchLastProducts() {
this.fetchLastProducts$.pipe(takeUntil(this.destroy$)).subscribe((_) => {
// Increase number of takes to show all residual products (currently: 10)
@@ -190,9 +210,7 @@ export class RemissionListComponent implements OnInit, OnDestroy {
takeUntil(this.destroy$),
tap((_) => this.store.dispatch(new SetRemissionIsLoading(false)))
)
.subscribe((result: { skip?: number; take?: number; hits?: number; items: RemissionProduct[]; completed: boolean }) => {
console.error('Subscribe [RemissionProducts]', result);
.subscribe((result: { skip?: number; take?: number; hits?: number; items: RemissionProduct[]; completed: boolean; }) => {
this.totalHits = result.hits;
this.updateFullListLoaded({
@@ -257,7 +275,10 @@ export class RemissionListComponent implements OnInit, OnDestroy {
this.isFullListLoaded = false;
}
private updateFullListLoaded(params: { totalHits: number; numberOfProductsFetched: number }) {
private updateFullListLoaded(params: { totalHits: number; numberOfProductsFetched: number; }) {
if (this.page === 0) {
return;
}
const allProductsFetched = params.numberOfProductsFetched >= this.totalHits;
allProductsFetched ? (this.isFullListLoaded = true) : (this.isFullListLoaded = false);
}

View File

@@ -44,6 +44,7 @@ export class RemissionShippingDocumentCardComponent {
.then(() => {
this.remissionHelper.addRemissionListItem(this.product);
this.updateShippingDocument.emit();
this.remissionHelper.requestRefetchProducts();
});
}

View File

@@ -5,4 +5,4 @@ import { RemissionListFilterModule } from './remission-list-filter/remission-lis
imports: [RemissionListFilterModule],
exports: [RemissionListFilterModule],
})
export class RemissionOverlaysModule {}
export class RemissionOverlaysModule { }

View File

@@ -1,5 +1,6 @@
<div
class="bg-branch"
(headerClicked)="close()"
[@topRightInOut]="animate"
(@topRightInOut.done)="closeAnimationDone()"
>

View File

@@ -7,10 +7,12 @@ import { SelectedFilterOptionsModule } from '../../../filter';
import { FilterGroupModule } from '../../../filter/filter-group/filter-group.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RemissionUeberlaufCapacitiesModule } from '../../pages/remission-list-create/ueberlauf-capacities';
import { SharedModule } from 'apps/sales/src/app/shared/shared.module';
@NgModule({
imports: [
CommonModule,
SharedModule,
IconModule,
SelectedFilterOptionsModule,
FilterGroupModule,
@@ -21,4 +23,4 @@ import { RemissionUeberlaufCapacitiesModule } from '../../pages/remission-list-c
declarations: [RemissionListFilterComponent],
entryComponents: [RemissionListFilterComponent],
})
export class RemissionListFilterModule {}
export class RemissionListFilterModule { }

View File

@@ -21,6 +21,7 @@ import { isNullOrUndefined } from 'util';
import { RemissionProcessStatuses } from 'apps/sales/src/app/core/models/remission-process-statuses.model';
import { RemissionToTopToBottomActionsComponent } from '../../../components/remission-to-top-to-bottom-actions';
import { UpdateShippingDocuent } from 'apps/sales/src/app/core/store/actions/remission.actions';
import { RemissionHelperService } from '../../../services';
@Component({
selector: 'app-remission-product-list',
@@ -279,7 +280,7 @@ export class RemissionProductListComponent implements OnInit, OnDestroy, AfterVi
);
}
private subscribeToIntersectionSub(params: { element: Element; sub: BehaviorSubject<boolean>; type: 'top' | 'bottom' }) {
private subscribeToIntersectionSub(params: { element: Element; sub: BehaviorSubject<boolean>; type: 'top' | 'bottom'; }) {
const { element, sub, type } = params;
const unsubscribe = this.intersectionObserverSubs.get(type);

View File

@@ -204,7 +204,7 @@ export class RemissionListStartedComponent implements OnInit, OnDestroy {
}
continueProcess(): Observable<RemissionProcess> {
return this.currentRemissionProcess$.pipe(filter((data) => !isNullOrUndefined(data), take(1))).pipe(
return this.currentRemissionProcess$.pipe(filter((data) => !isNullOrUndefined(data)), take(1)).pipe(
switchMap((process) => {
return this.remissionService.continueProcess(process);
}),

View File

@@ -8,6 +8,7 @@ import { RemissionResourceType } from '../models/remission-resource-type.model';
providedIn: 'root'
})
export class RemissionHelperService {
refetchProducts$ = new Subject<void>();
filteOptionsDeleteEvents$ = new Subject<FilterOption>();
filtersClearedEvent$ = new Subject();
closeFilters$ = new Subject();
@@ -17,10 +18,11 @@ export class RemissionHelperService {
remissionListHits$ = new BehaviorSubject<number>(null);
deleteRemissionListItem$ = new Subject<RemissionProduct>();
addRemissionListItem$ = new Subject<RemissionProduct>();
updateRemissionListItem$ = new Subject<{ quantity: number; product: RemissionProduct }>();
updateRemissionListItem$ = new Subject<{ quantity: number; product: RemissionProduct; }>();
filterHeight$ = new BehaviorSubject<number>(null);
constructor() {}
constructor() { }
public requestRefetchProducts = () => this.refetchProducts$.next();
public deleteFilterOption = (option: FilterOption) => this.filteOptionsDeleteEvents$.next(option);
public clearFilters = () => this.filtersClearedEvent$.next();
public closeFilters = () => this.closeFilters$.next();

View File

@@ -1,11 +1,15 @@
<div class="shelf-search-container" [ngClass]="{ 'shelf-search-container-mobile': isIPad }">
<div
class="shelf-search-container"
[ngClass]="{ 'shelf-search-container-mobile': isIPad }"
>
<div class="shelf-section shelf-search">
<div class="align-center shelf-search-title-margin">
<span class="shelf-search-title">Bestellpostensuche</span>
</div>
<div class="align-center">
<span class="shelf-search-description">
Suchen Sie den Bestellposten via Name, Abholfachnummer, Abholscheinnummer, Kudenkartennummer oder Vorgang-ID.
Suchen Sie den Bestellposten via Name, Abholfachnummer,
Abholscheinnummer, Kundenkartennummer oder Vorgang-ID.
</span>
</div>
<div class="align-center search-container">

View File

@@ -0,0 +1,32 @@
import { Directive, ElementRef, Output, EventEmitter, HostListener, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { skip, takeUntil } from 'rxjs/operators';
@Directive({ selector: '[clickOutside]' })
export class ClickOutsideDirective implements OnInit, OnDestroy {
clickedInside$ = new Subject();
destroy$ = new Subject();
@Output() clickOutside = new EventEmitter<void>();
@HostListener('document:click', ['$event.target'])
@HostListener('document:touchstart', ['$event.target'])
onClick(target: HTMLElement) {
const isClickedInside = this.elementRef.nativeElement.contains(target);
if (!isClickedInside) {
this.clickedInside$.next();
}
}
constructor(private elementRef: ElementRef) { }
ngOnInit() {
this.clickedInside$.pipe(takeUntil(this.destroy$), skip(1)).subscribe(_ => this.clickOutside.emit());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}

View File

@@ -0,0 +1,33 @@
import { Directive, ElementRef, Output, EventEmitter, HostListener, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { skip, takeUntil } from 'rxjs/operators';
@Directive({ selector: '[headerClicked]' })
export class HeaderClickedDirective implements OnInit, OnDestroy {
headerClicked$ = new Subject();
destroy$ = new Subject();
header = document.body.querySelector('.app-header');
@Output() headerClicked = new EventEmitter<void>();
@HostListener('document:click', ['$event.target'])
@HostListener('document:touchstart', ['$event.target'])
onClick(target: HTMLElement) {
const isHeaderClicked = this.header.contains(target);
if (isHeaderClicked) {
this.headerClicked$.next();
}
}
constructor(private elementRef: ElementRef) { }
ngOnInit() {
this.headerClicked$.pipe(takeUntil(this.destroy$)).subscribe(_ => this.headerClicked.emit());
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}

View File

@@ -0,0 +1,8 @@
// start:ng42.barrel
export * from './add-class.directive';
export * from './click-outside.directive';
export * from './header-clicked.directive';
export * from './tooltip.directive';
export * from './var.directive';
// end:ng42.barrel

View File

@@ -15,9 +15,10 @@ import { PackageNumberParserPipe } from '../pipes/package-number-parser.pipe';
import { AddClassDirective } from './directives/add-class.directive';
import { ShippingDocumentNumberFormatterPipe } from '../pipes/shipping-document-number-formatter.pipe';
import { RemissionSourcesDisplayPipe } from '../pipes/remission-sources-display.pipe';
import { ClickOutsideDirective, HeaderClickedDirective } from './directives';
const components = [BackArrowComponent, ModalDialogComponent];
const directives = [VarDirective, TooltipDirective, AddClassDirective];
const directives = [VarDirective, TooltipDirective, AddClassDirective, ClickOutsideDirective, HeaderClickedDirective];
const pipes = [
SafeHtmlPipe,
BookPricePipe,
@@ -35,4 +36,4 @@ const pipes = [
declarations: [...components, ...directives, ...pipes],
providers: []
})
export class SharedModule {}
export class SharedModule { }

View File

@@ -25,6 +25,10 @@ jobs:
- docker
condition: and(ne(variables['Build.SourceBranch'], 'refs/heads/integration'), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
steps:
- task: npmAuthenticate@0
displayName: 'npm auth'
inputs:
workingFile: .npmrc
- task: Docker@2
displayName: 'build ISAClient Debug'
inputs:
@@ -42,6 +46,10 @@ jobs:
- docker
condition: or(eq(variables['Build.SourceBranch'], 'refs/heads/integration'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
steps:
- task: npmAuthenticate@0
displayName: 'npm auth'
inputs:
workingFile: .npmrc
- task: Docker@2
displayName: 'build ISAClient Debug'
inputs:
@@ -82,6 +90,10 @@ jobs:
- docker
condition: or(eq(variables['Build.SourceBranch'], 'refs/heads/integration'), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
steps:
- task: npmAuthenticate@0
displayName: 'npm auth'
inputs:
workingFile: .npmrc
- task: Docker@2
displayName: 'build ISAClient Prod'
inputs: