mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merge develop
This commit is contained in:
5
.npmrc
5
.npmrc
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ export interface Product {
|
||||
location: string;
|
||||
ean: string;
|
||||
imageId: string;
|
||||
ssc: string,
|
||||
sscText: string;
|
||||
storeStatusCode: number;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ export class RemissionShippingDocumentCardComponent {
|
||||
.then(() => {
|
||||
this.remissionHelper.addRemissionListItem(this.product);
|
||||
this.updateShippingDocument.emit();
|
||||
this.remissionHelper.requestRefetchProducts();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ import { RemissionListFilterModule } from './remission-list-filter/remission-lis
|
||||
imports: [RemissionListFilterModule],
|
||||
exports: [RemissionListFilterModule],
|
||||
})
|
||||
export class RemissionOverlaysModule {}
|
||||
export class RemissionOverlaysModule { }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<div
|
||||
class="bg-branch"
|
||||
(headerClicked)="close()"
|
||||
[@topRightInOut]="animate"
|
||||
(@topRightInOut.done)="closeAnimationDone()"
|
||||
>
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}),
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
8
apps/sales/src/app/shared/directives/index.ts
Normal file
8
apps/sales/src/app/shared/directives/index.ts
Normal 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
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user