@colijnit/product 258.1.5 → 258.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/image-carousel/image-carousel.component.d.ts +5 -0
- package/app/components/product-addtocart/product-addtocart.component.d.ts +5 -1
- package/app/components/product-page/product-page.component.d.ts +1 -0
- package/app/service/product-connector-adapter.service.d.ts +1 -0
- package/app/service/product-connector.service.d.ts +2 -0
- package/bundles/colijnit-product.umd.js +166 -67
- package/bundles/colijnit-product.umd.js.map +1 -1
- package/colijnit-product-258.1.5.tgz +0 -0
- package/colijnit-product.metadata.json +1 -1
- package/esm2015/app/components/image-carousel/image-carousel.component.js +82 -36
- package/esm2015/app/components/product-addtocart/product-addtocart.component.js +38 -8
- package/esm2015/app/components/product-info-tabs/product-info-tabs.component.js +2 -2
- package/esm2015/app/components/product-page/product-page.component.js +19 -6
- package/esm2015/app/product-version.js +3 -3
- package/esm2015/app/service/product-connector-adapter.service.js +9 -1
- package/esm2015/app/service/product-connector.service.js +5 -1
- package/fesm2015/colijnit-product.js +151 -51
- package/fesm2015/colijnit-product.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Directive, Injectable, EventEmitter, Component, ViewEncapsulation, Input, Output, Renderer2, ChangeDetectorRef, ViewChild, ElementRef, Pipe, NgModule, ChangeDetectionStrategy, HostListener, HostBinding, SecurityContext, CUSTOM_ELEMENTS_SCHEMA, Inject, PLATFORM_ID, NO_ERRORS_SCHEMA } from '@angular/core';
|
|
3
3
|
import { __awaiter } from 'tslib';
|
|
4
|
-
import { Subject, BehaviorSubject } from 'rxjs';
|
|
4
|
+
import { Subject, BehaviorSubject, combineLatest } from 'rxjs';
|
|
5
5
|
import { Options } from '@colijnit/ioneconnector/build/model/options';
|
|
6
6
|
import { ArticleFullObject } from '@colijnit/articleapi/build/model/article-full-object';
|
|
7
7
|
import { SuperArticle } from '@colijnit/articleapi/build/model/super-article';
|
|
@@ -30,8 +30,8 @@ class Version {
|
|
|
30
30
|
constructor() {
|
|
31
31
|
this.name = "@colijnit/product";
|
|
32
32
|
this.description = "Product detail page project for iOne";
|
|
33
|
-
this.symVer = "258.1.
|
|
34
|
-
this.publishDate = "
|
|
33
|
+
this.symVer = "258.1.6";
|
|
34
|
+
this.publishDate = "22-8-2025 14:23:38";
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -204,6 +204,14 @@ class ProductConnectorAdapterService {
|
|
|
204
204
|
});
|
|
205
205
|
});
|
|
206
206
|
}
|
|
207
|
+
getGeneratedArtDirectly(goodId, showLoader) {
|
|
208
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
209
|
+
return this.articleConnector.getGeneratedArtDirectly(goodId, showLoader).catch((messages) => {
|
|
210
|
+
this._eventService.errorMessage.next(messages);
|
|
211
|
+
return null;
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
207
215
|
getGoodIdFromArticleNr(sku) {
|
|
208
216
|
return __awaiter(this, void 0, void 0, function* () {
|
|
209
217
|
const response = yield this.articleConnector.getGoodIdFromArticleNr(sku);
|
|
@@ -571,6 +579,7 @@ class ProductConnectorService {
|
|
|
571
579
|
this._adapterService = _adapterService;
|
|
572
580
|
this._settingsService = _settingsService;
|
|
573
581
|
this.controllerInitialized = new BehaviorSubject(false);
|
|
582
|
+
this.articleLoaded = new BehaviorSubject(false);
|
|
574
583
|
this._initializing = false;
|
|
575
584
|
this._initialized = false;
|
|
576
585
|
this.connectorOptions = new Options();
|
|
@@ -648,6 +657,9 @@ class ProductConnectorService {
|
|
|
648
657
|
getJsonArticleFlatTree(goodId, goodType, quantity, externalSource = false, showLoader = true, configuratorStatistics) {
|
|
649
658
|
return this._adapterService.getJsonArticleFlatTree(goodId, goodType, quantity, externalSource, showLoader, this._instanceId, configuratorStatistics);
|
|
650
659
|
}
|
|
660
|
+
getGeneratedArtDirectly(goodId, showLoader = true) {
|
|
661
|
+
return this._adapterService.getGeneratedArtDirectly(goodId, showLoader);
|
|
662
|
+
}
|
|
651
663
|
addWebSessionTransactionLine(transactionUuid, sku, quantity) {
|
|
652
664
|
return __awaiter(this, void 0, void 0, function* () {
|
|
653
665
|
return yield this._adapterService.addWebSessionTransactionLine(transactionUuid, sku, quantity);
|
|
@@ -981,9 +993,18 @@ class ProductPageComponent {
|
|
|
981
993
|
if (this.selections.nativeElement) {
|
|
982
994
|
this.selections.nativeElement.forceRenderImage();
|
|
983
995
|
}
|
|
984
|
-
}), this.settingsService.settingsLoaded.subscribe(loaded => this._handleSettingsLoaded(loaded)), this.
|
|
985
|
-
this.
|
|
986
|
-
|
|
996
|
+
}), this.settingsService.settingsLoaded.subscribe(loaded => this._handleSettingsLoaded(loaded)), this._pageLoadedSubscription = combineLatest([
|
|
997
|
+
this._ione.controllerInitialized,
|
|
998
|
+
this._ione.articleLoaded
|
|
999
|
+
]).subscribe(([initialized, articleLoaded]) => {
|
|
1000
|
+
if (initialized && articleLoaded) {
|
|
1001
|
+
this.settingsLoaded = initialized;
|
|
1002
|
+
}
|
|
1003
|
+
}),
|
|
1004
|
+
// this._ione.controllerInitialized.subscribe((initialized: boolean) => {
|
|
1005
|
+
// this.settingsLoaded = initialized;
|
|
1006
|
+
// }),
|
|
1007
|
+
this.appEventService.onAnswersAvailable.subscribe((answers) => {
|
|
987
1008
|
if (answers && this.configurable) {
|
|
988
1009
|
this.showAddToCart = false;
|
|
989
1010
|
}
|
|
@@ -1063,6 +1084,7 @@ class ProductPageComponent {
|
|
|
1063
1084
|
if (this._initializedSub) {
|
|
1064
1085
|
this._initializedSub.unsubscribe();
|
|
1065
1086
|
}
|
|
1087
|
+
this._pageLoadedSubscription.unsubscribe();
|
|
1066
1088
|
this.configurator = undefined;
|
|
1067
1089
|
this.selections = undefined;
|
|
1068
1090
|
this.fullscreenbutton = undefined;
|
|
@@ -1094,7 +1116,8 @@ class ProductPageComponent {
|
|
|
1094
1116
|
this._ione.getFullArticle(this._sku).then((article) => {
|
|
1095
1117
|
this.article = article;
|
|
1096
1118
|
if (this.article) {
|
|
1097
|
-
this.configurable = this.article.goodType === 'B';
|
|
1119
|
+
this.configurable = this.article.goodType === 'B' && (this.article.isConfigurable || this.article.isConfigurable === undefined);
|
|
1120
|
+
// this.configurable = this.article.goodType === 'B';
|
|
1098
1121
|
if (this.configurable) {
|
|
1099
1122
|
this.showAddToCart = false;
|
|
1100
1123
|
this.currentView = SelectorType.TwoD;
|
|
@@ -1111,6 +1134,7 @@ class ProductPageComponent {
|
|
|
1111
1134
|
});
|
|
1112
1135
|
this._changeDetector.detectChanges();
|
|
1113
1136
|
}
|
|
1137
|
+
this._ione.articleLoaded.next(true);
|
|
1114
1138
|
});
|
|
1115
1139
|
}
|
|
1116
1140
|
}));
|
|
@@ -1127,7 +1151,7 @@ class ProductPageComponent {
|
|
|
1127
1151
|
ProductPageComponent.decorators = [
|
|
1128
1152
|
{ type: Component, args: [{
|
|
1129
1153
|
selector: 'app-product-page',
|
|
1130
|
-
template: "<ng-container *ngIf=\"settingsLoaded\">\r\n <div class=\"page-wrapper\">\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\">\r\n <div class=\"product-image-container\">\r\n <div class=\"product-page-block-selector-type\">\r\n <app-product-selector-type class=\"default-padding\"\r\n [(currentType)]=\"currentView\"\r\n [show2D]=\"configurable\"\r\n [show3D]=\"threeD\"\r\n ></app-product-selector-type>\r\n </div>\r\n <div class=\"product-page-block-image default-padding\" [class.full]=\"fullScreen\">\r\n\r\n <app-image-carousel\r\n *ngIf=\"!enableRenderCarousel\"\r\n [@toggleVisibilityByState]=\"show2D ? 'show' : 'hide'\"\r\n [images]=\"article?.images\"\r\n [showRefresh]=\"configurable && threeD\">\r\n </app-image-carousel>\r\n\r\n <app-render-carousel\r\n *ngIf=\"enableRenderCarousel\"\r\n [@toggleVisibilityByState]=\"show2D ? 'show' : 'hide'\"\r\n [article]=\"article\">\r\n </app-render-carousel>\r\n\r\n <ng-container *ngIf=\"settingsLoaded\">\r\n <threed-configurator\r\n #configurator\r\n class=\"threed-configurator\"\r\n [class.configurator-full-screen]=\"fullScreen\"\r\n [@toggleVisibilityByState]=\"show3D ? 'show' : 'hide'\"\r\n [@toggleFullScreen]=\"fullScreen ? 'fullscreen' : 'halfscreen'\">\r\n </threed-configurator>\r\n </ng-container>\r\n\r\n <co-icon #fullscreenbutton class=\"fullscreen-button\" *ngIf=\"show3D\"\r\n [@toggleTopLeft]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [iconData]=\"iconCache.getIcon(fullScreenIcon)\"\r\n (click)=\"showFullScreen()\"></co-icon>\r\n <co-icon class=\"threed-watermark\" *ngIf=\"show3D && fullScreen\"\r\n [iconData]=\"iconCache.getIcon(icon.Logo)\"></co-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-description\">\r\n <app-product-description class=\"default-padding\" [article]=\"article\"></app-product-description>\r\n </div>\r\n <div class=\"product-page-block-additional\">\r\n <div class=\"product-page-block-additional-description\">\r\n <app-product-additional-description class=\"default-padding\" [article]=\"article\"></app-product-additional-description>\r\n </div>\r\n <div class=\"product-page-block-price\" [class.full]=\"configuring\">\r\n <app-product-price class=\"s-padding\" *ngIf=\"!configuring\"\r\n [pricing]=\"article?.pricing\"\r\n [configurable]=\"configurable\"\r\n ></app-product-price>\r\n <ng-container *ngIf=\"settingsLoaded\">\r\n <threed-selections #selections class=\"threed-selections\"\r\n [class.show-selections]=\"configuring\"\r\n [@toggleFullScreenRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [class.default-padding]=\"!fullScreen\"\r\n [class.show-full-screen]=\"fullScreen\"\r\n [class.mini-scrollbar]=\"fullScreen\"\r\n [sku]=\"sku\"\r\n [settings]=\"settings\"\r\n (onUserActionFromThreeD)=\"configuring = true\"\r\n (instanceSet)=\"setInstance($event)\"\r\n (onImageReceived)=\"appEventService.onImageReceived.next($event)\"\r\n (onRenderStarted)=\"appEventService.onRenderStarted.next()\"\r\n (onDraftRenderImageReceived)=\"appEventService.onDraftRenderImageReceived.next($event)\"\r\n (onArticleReceived)=\"appEventService.onArticleReceived.next($event.detail)\"\r\n (onSelectionsReceived)=\"appEventService.onSelectionsReceived.next($event.detail)\"\r\n (onArticleInfoReceived)=\"appEventService.onArticleInfoReceived.next($event.detail)\"\r\n (onAnswersAvailable)=\"appEventService.onAnswersAvailable.next($event.detail)\"\r\n (onReadyToRender)=\"appEventService.onReadyToRender.next($event.detail)\"\r\n (onRenderImageReceived)=\"appEventService.onRenderImageReceived.next($event.detail)\"\r\n ></threed-selections>\r\n </ng-container>\r\n </div>\r\n <div class=\"product-page-block-addtocart no-padding product-action-buttons\" *ngIf=\"!configuring\" [@toggleTopRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\">\r\n <app-product-addtocart\r\n [configurable]=\"configurable\"\r\n [createFrozenArticle]=\"createFrozenArticle\"\r\n [configuring]=\"configuring\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n (showRelatedPopup)=\"handlePopUpChange($event)\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"addtocart-reserved product-action-buttons\" *ngIf=\"configuring\" [class.full-screen]=\"fullScreen\">\r\n <app-product-addtocart class=\"default-padding\"\r\n [configurable]=\"false\"\r\n [fullscreen]=\"fullScreen\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [configuring]=\"configuring\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"product-page-block-variants\">\r\n <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>\r\n </div>\r\n <div class=\"product-page-block-stock\">\r\n <app-product-stock class=\"no-padding\" [goodId]=\"article?.goodId\" (openStockEvent)=\"openStock()\"></app-product-stock>\r\n </div>\r\n <div class=\"product-page-block-delivery\">\r\n <app-product-delivery class=\"no-padding\" [stockAndDelivery]=\"stockAndDelivery\"></app-product-delivery>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\">\r\n <app-product-info-tabs class=\"no-padding\" [article]=\"article\"></app-product-info-tabs>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-related s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n [label]=\"'RELATED_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content no-top-margin\">\r\n <div class=\"page-wrapper-full\">\r\n <div class=\"product-page-block-alternatives s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"4\"\r\n [isSmallModus]=\"false\"\r\n [label]=\"'ALTERNATIVE_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngIf=\"showRelatedProductsPopup\">\r\n <co-product-dialog\r\n [mainArticle]=\"article\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n (closeRelatedPopup)=\"handlePopUpChange($event)\"\r\n >\r\n </co-product-dialog>\r\n\r\n <!-- <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"-->\r\n <!-- [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>-->\r\n </div>\r\n\r\n\r\n </div>\r\n</ng-container>\r\n",
|
|
1154
|
+
template: "<ng-container *ngIf=\"settingsLoaded\">\r\n <div class=\"page-wrapper\">\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\">\r\n <div class=\"product-image-container\">\r\n <div class=\"product-page-block-selector-type\">\r\n <app-product-selector-type class=\"default-padding\"\r\n [(currentType)]=\"currentView\"\r\n [show2D]=\"configurable\"\r\n [show3D]=\"threeD\"\r\n ></app-product-selector-type>\r\n </div>\r\n <div class=\"product-page-block-image default-padding\" [class.full]=\"fullScreen\">\r\n\r\n <app-image-carousel\r\n *ngIf=\"!enableRenderCarousel\"\r\n [@toggleVisibilityByState]=\"show2D ? 'show' : 'hide'\"\r\n [images]=\"article?.images\"\r\n [showRefresh]=\"configurable && threeD\">\r\n </app-image-carousel>\r\n\r\n <app-render-carousel\r\n *ngIf=\"enableRenderCarousel\"\r\n [@toggleVisibilityByState]=\"show2D ? 'show' : 'hide'\"\r\n [article]=\"article\">\r\n </app-render-carousel>\r\n\r\n <ng-container *ngIf=\"settingsLoaded && this.configurable\">\r\n <threed-configurator\r\n #configurator\r\n class=\"threed-configurator\"\r\n [class.configurator-full-screen]=\"fullScreen\"\r\n [@toggleVisibilityByState]=\"show3D ? 'show' : 'hide'\"\r\n [@toggleFullScreen]=\"fullScreen ? 'fullscreen' : 'halfscreen'\">\r\n </threed-configurator>\r\n </ng-container>\r\n\r\n <co-icon #fullscreenbutton class=\"fullscreen-button\" *ngIf=\"show3D\"\r\n [@toggleTopLeft]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [iconData]=\"iconCache.getIcon(fullScreenIcon)\"\r\n (click)=\"showFullScreen()\"></co-icon>\r\n <co-icon class=\"threed-watermark\" *ngIf=\"show3D && fullScreen\"\r\n [iconData]=\"iconCache.getIcon(icon.Logo)\"></co-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-description\">\r\n <app-product-description class=\"default-padding\" [article]=\"article\"></app-product-description>\r\n </div>\r\n <div class=\"product-page-block-additional\">\r\n <div class=\"product-page-block-additional-description\">\r\n <app-product-additional-description class=\"default-padding\" [article]=\"article\"></app-product-additional-description>\r\n </div>\r\n <div class=\"product-page-block-price\" [class.full]=\"configuring\">\r\n <app-product-price class=\"s-padding\" *ngIf=\"!configuring\"\r\n [pricing]=\"article?.pricing\"\r\n [configurable]=\"configurable\"\r\n ></app-product-price>\r\n <ng-container *ngIf=\"settingsLoaded\">\r\n <threed-selections #selections class=\"threed-selections\"\r\n [class.show-selections]=\"configuring\"\r\n [@toggleFullScreenRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [class.default-padding]=\"!fullScreen\"\r\n [class.show-full-screen]=\"fullScreen\"\r\n [class.mini-scrollbar]=\"fullScreen\"\r\n [sku]=\"sku\"\r\n [settings]=\"settings\"\r\n (onUserActionFromThreeD)=\"configuring = true\"\r\n (instanceSet)=\"setInstance($event)\"\r\n (onImageReceived)=\"appEventService.onImageReceived.next($event)\"\r\n (onRenderStarted)=\"appEventService.onRenderStarted.next()\"\r\n (onDraftRenderImageReceived)=\"appEventService.onDraftRenderImageReceived.next($event)\"\r\n (onArticleReceived)=\"appEventService.onArticleReceived.next($event.detail)\"\r\n (onSelectionsReceived)=\"appEventService.onSelectionsReceived.next($event.detail)\"\r\n (onArticleInfoReceived)=\"appEventService.onArticleInfoReceived.next($event.detail)\"\r\n (onAnswersAvailable)=\"appEventService.onAnswersAvailable.next($event.detail)\"\r\n (onReadyToRender)=\"appEventService.onReadyToRender.next($event.detail)\"\r\n (onRenderImageReceived)=\"appEventService.onRenderImageReceived.next($event.detail)\"\r\n ></threed-selections>\r\n </ng-container>\r\n </div>\r\n <div class=\"product-page-block-addtocart no-padding product-action-buttons\" *ngIf=\"!configuring\" [@toggleTopRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\">\r\n <app-product-addtocart\r\n [configurable]=\"configurable\"\r\n [createFrozenArticle]=\"createFrozenArticle\"\r\n [configuring]=\"configuring\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n (showRelatedPopup)=\"handlePopUpChange($event)\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"addtocart-reserved product-action-buttons\" *ngIf=\"configuring\" [class.full-screen]=\"fullScreen\">\r\n <app-product-addtocart class=\"default-padding\"\r\n [configurable]=\"false\"\r\n [fullscreen]=\"fullScreen\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [configuring]=\"configuring\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"product-page-block-variants\">\r\n <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>\r\n </div>\r\n <div class=\"product-page-block-stock\">\r\n <app-product-stock class=\"no-padding\" [goodId]=\"article?.goodId\" (openStockEvent)=\"openStock()\"></app-product-stock>\r\n </div>\r\n <div class=\"product-page-block-delivery\">\r\n <app-product-delivery class=\"no-padding\" [stockAndDelivery]=\"stockAndDelivery\"></app-product-delivery>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\" *ngIf=\"article\">\r\n <app-product-info-tabs class=\"no-padding\" [article]=\"article\"></app-product-info-tabs>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-related s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n [label]=\"'RELATED_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content no-top-margin\">\r\n <div class=\"page-wrapper-full\">\r\n <div class=\"product-page-block-alternatives s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"4\"\r\n [isSmallModus]=\"false\"\r\n [label]=\"'ALTERNATIVE_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngIf=\"showRelatedProductsPopup\">\r\n <co-product-dialog\r\n [mainArticle]=\"article\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n (closeRelatedPopup)=\"handlePopUpChange($event)\"\r\n >\r\n </co-product-dialog>\r\n\r\n <!-- <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"-->\r\n <!-- [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>-->\r\n </div>\r\n\r\n\r\n </div>\r\n</ng-container>\r\n",
|
|
1131
1155
|
animations: [
|
|
1132
1156
|
trigger('toggleFullScreen', [
|
|
1133
1157
|
state('fullscreen', style({ 'position': 'fixed', 'top': '0', 'left': '0', 'width': '100%', 'height': '100%' })),
|
|
@@ -1314,6 +1338,7 @@ class ImageCarouselComponent {
|
|
|
1314
1338
|
this._appEventService = _appEventService;
|
|
1315
1339
|
this._changeDetector = _changeDetector;
|
|
1316
1340
|
this._domSanitizer = _domSanitizer;
|
|
1341
|
+
this.isPopupOpen = false;
|
|
1317
1342
|
this.showRefresh = false;
|
|
1318
1343
|
this.resizing = false;
|
|
1319
1344
|
this.imageViewModels = [];
|
|
@@ -1343,6 +1368,12 @@ class ImageCarouselComponent {
|
|
|
1343
1368
|
this._changeDetector.detectChanges();
|
|
1344
1369
|
}));
|
|
1345
1370
|
}
|
|
1371
|
+
// Close on ESC
|
|
1372
|
+
onEsc() {
|
|
1373
|
+
if (this.isPopupOpen) {
|
|
1374
|
+
this.closePopup();
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1346
1377
|
set images(value) {
|
|
1347
1378
|
if (value && value.length > 0) {
|
|
1348
1379
|
this._images = this._filterValidImages(value);
|
|
@@ -1389,15 +1420,16 @@ class ImageCarouselComponent {
|
|
|
1389
1420
|
}
|
|
1390
1421
|
handleShowImage(imageViewModel) {
|
|
1391
1422
|
if (imageViewModel && imageViewModel.originalSource) {
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
popupWindow.document.write(`<img src=${imageViewModel.originalSource} alt="Image" style="width:100%; height:auto;">`);
|
|
1396
|
-
popupWindow.document.write('</body></html>');
|
|
1397
|
-
// Close the document to render the popup window
|
|
1398
|
-
popupWindow.document.close();
|
|
1423
|
+
this.selectedImage = imageViewModel;
|
|
1424
|
+
this.isPopupOpen = true;
|
|
1425
|
+
this._changeDetector.markForCheck();
|
|
1399
1426
|
}
|
|
1400
1427
|
}
|
|
1428
|
+
closePopup() {
|
|
1429
|
+
this.isPopupOpen = false;
|
|
1430
|
+
this.selectedImage = undefined;
|
|
1431
|
+
this._changeDetector.markForCheck();
|
|
1432
|
+
}
|
|
1401
1433
|
_filterValidImages(value) {
|
|
1402
1434
|
if (!value) {
|
|
1403
1435
|
return [];
|
|
@@ -1440,38 +1472,54 @@ class ImageCarouselComponent {
|
|
|
1440
1472
|
}
|
|
1441
1473
|
_resizeAndSanitizeSource(source, imageViewModel) {
|
|
1442
1474
|
const resizeCanvas = document.createElement('canvas');
|
|
1443
|
-
const
|
|
1444
|
-
const
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
const
|
|
1451
|
-
const
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
let newHeight = this._resizeCanvasHeight;
|
|
1457
|
-
if (originalWidth > originalHeight) {
|
|
1458
|
-
newHeight = this._resizeCanvasHeight / aspectRatio;
|
|
1475
|
+
const ctx = resizeCanvas.getContext('2d');
|
|
1476
|
+
const img = document.createElement('img');
|
|
1477
|
+
img.crossOrigin = 'anonymous';
|
|
1478
|
+
img.onload = () => {
|
|
1479
|
+
ctx.imageSmoothingEnabled = true;
|
|
1480
|
+
ctx.imageSmoothingQuality = 'high';
|
|
1481
|
+
const ow = img.width;
|
|
1482
|
+
const oh = img.height;
|
|
1483
|
+
const aspect = ow / oh;
|
|
1484
|
+
let newW = this._resizeCanvasHeight;
|
|
1485
|
+
let newH = this._resizeCanvasHeight;
|
|
1486
|
+
if (ow > oh) {
|
|
1487
|
+
newH = this._resizeCanvasHeight / aspect;
|
|
1459
1488
|
}
|
|
1460
1489
|
else {
|
|
1461
|
-
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
resizeCanvas.
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
const
|
|
1490
|
+
newW = this._resizeCanvasHeight * aspect;
|
|
1491
|
+
}
|
|
1492
|
+
resizeCanvas.width = Math.round(newW);
|
|
1493
|
+
resizeCanvas.height = Math.round(newH);
|
|
1494
|
+
// Ensure transparent background before drawing
|
|
1495
|
+
ctx.clearRect(0, 0, resizeCanvas.width, resizeCanvas.height);
|
|
1496
|
+
ctx.drawImage(img, 0, 0, resizeCanvas.width, resizeCanvas.height);
|
|
1497
|
+
const mime = this._detectPreferredMime(source);
|
|
1498
|
+
const resizedSource = mime === 'image/jpeg'
|
|
1499
|
+
? resizeCanvas.toDataURL('image/jpeg', 0.92) // only if original was JPEG
|
|
1500
|
+
: resizeCanvas.toDataURL(mime); // PNG/WebP keep alpha
|
|
1469
1501
|
imageViewModel.source = this._domSanitizer.bypassSecurityTrustUrl(resizedSource);
|
|
1470
1502
|
imageViewModel.originalSource = source;
|
|
1471
1503
|
this._changeDetector.detectChanges();
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
|
|
1504
|
+
};
|
|
1505
|
+
img.src = source;
|
|
1506
|
+
}
|
|
1507
|
+
_detectPreferredMime(source) {
|
|
1508
|
+
// Data URI check
|
|
1509
|
+
const m = source.match(/^data:(image\/[a-zA-Z+.-]+);base64,/);
|
|
1510
|
+
if (m) {
|
|
1511
|
+
const t = m[1].toLowerCase();
|
|
1512
|
+
if (t === 'image/png' || t === 'image/webp' || t === 'image/jpeg')
|
|
1513
|
+
return t;
|
|
1514
|
+
}
|
|
1515
|
+
const lower = source.toLowerCase();
|
|
1516
|
+
if (lower.endsWith('.png'))
|
|
1517
|
+
return 'image/png';
|
|
1518
|
+
if (lower.endsWith('.webp'))
|
|
1519
|
+
return 'image/webp';
|
|
1520
|
+
if (lower.endsWith('.jpg') || lower.endsWith('.jpeg'))
|
|
1521
|
+
return 'image/jpeg';
|
|
1522
|
+
return 'image/png';
|
|
1475
1523
|
}
|
|
1476
1524
|
_scrollCarouselToIndex() {
|
|
1477
1525
|
if (this.currentIndex > -1 && this.currentIndex <= this.images.length) {
|
|
@@ -1521,9 +1569,31 @@ ImageCarouselComponent.decorators = [
|
|
|
1521
1569
|
</co-scroll-container>
|
|
1522
1570
|
</div>
|
|
1523
1571
|
</div>
|
|
1572
|
+
<!-- Modal (real popup) -->
|
|
1573
|
+
<div
|
|
1574
|
+
class="image-modal"
|
|
1575
|
+
*ngIf="isPopupOpen"
|
|
1576
|
+
(click)="closePopup()"
|
|
1577
|
+
role="dialog"
|
|
1578
|
+
aria-modal="true"
|
|
1579
|
+
aria-label="Image preview"
|
|
1580
|
+
>
|
|
1581
|
+
<div class="image-modal__content" (click)="$event.stopPropagation()">
|
|
1582
|
+
<button
|
|
1583
|
+
class="image-modal__close"
|
|
1584
|
+
type="button"
|
|
1585
|
+
aria-label="Close"
|
|
1586
|
+
(click)="closePopup()"
|
|
1587
|
+
>
|
|
1588
|
+
×
|
|
1589
|
+
</button>
|
|
1590
|
+
|
|
1591
|
+
<img [src]="selectedImage?.originalSource" alt="Image preview" />
|
|
1592
|
+
</div>
|
|
1593
|
+
</div>
|
|
1524
1594
|
`,
|
|
1525
1595
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1526
|
-
styles: [":host{max-height:540px;height:100%;position:relative}:host:not(.resizing) .inner-carousel{scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory}#product_page_carousel{position:relative}#product_page_carousel .refresh-button{position:absolute;bottom:10px;right:10px;background:#fff}#product_page_carousel .refresh-button.loading{animation:spin 1s linear infinite}#product_page_carousel .refresh-button:hover{box-shadow:none;background:#74B77F;transition:all .2s ease-in-out}#product_page_carousel .refresh-button:hover ::ng-deep svg path{fill:#fff!important}#product_page_carousel #product_page_carousel_items{position:relative;margin-bottom:10px}#product_page_carousel #product_page_carousel_items ::ng-deep co-loader{position:absolute}#product_page_carousel .inner-carousel{display:flex;flex-direction:row;align-items:center;overflow:hidden;max-height:500px;border:1px solid #efefef}#product_page_carousel .carousel-item{max-height:500px;width:100%;display:flex;cursor:zoom-in;flex-shrink:0;flex-grow:0}#product_page_carousel .carousel-item img{width:100%;height:auto;-o-object-fit:contain;object-fit:contain}#product_page_carousel .carousel-scroller-layer{height:100%;width:100%;position:absolute;pointer-events:none;top:0;left:0}#product_page_carousel #product_page_carousel_thumbs{display:flex;justify-content:flex-start;height:80px;margin-left:auto;margin-right:auto}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container{padding:0 22px}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container .content-wrapper{padding:0}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb{opacity:1;cursor:pointer;transition:all .2s ease;padding:4px;border:1px solid #f6f5f4}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb.active,#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:hover{border-color:#22313c}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:not(:last-child){margin-right:10px}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb img{height:68px}@media screen and (max-width: 650px){#product_page_carousel_thumbs{height:57px!important}#product_page_carousel_thumbs .carousel-thumb img{height:50px!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"]
|
|
1596
|
+
styles: [":host{max-height:540px;height:100%;position:relative}:host:not(.resizing) .inner-carousel{scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory}#product_page_carousel{position:relative}#product_page_carousel .refresh-button{position:absolute;bottom:10px;right:10px;background:#fff}#product_page_carousel .refresh-button.loading{animation:spin 1s linear infinite}#product_page_carousel .refresh-button:hover{box-shadow:none;background:#74B77F;transition:all .2s ease-in-out}#product_page_carousel .refresh-button:hover ::ng-deep svg path{fill:#fff!important}#product_page_carousel #product_page_carousel_items{position:relative;margin-bottom:10px}#product_page_carousel #product_page_carousel_items ::ng-deep co-loader{position:absolute}#product_page_carousel .inner-carousel{display:flex;flex-direction:row;align-items:center;overflow:hidden;max-height:500px;border:1px solid #efefef}#product_page_carousel .carousel-item{max-height:500px;width:100%;display:flex;cursor:zoom-in;flex-shrink:0;flex-grow:0}#product_page_carousel .carousel-item img{width:100%;height:auto;-o-object-fit:contain;object-fit:contain}#product_page_carousel .carousel-scroller-layer{height:100%;width:100%;position:absolute;pointer-events:none;top:0;left:0}#product_page_carousel #product_page_carousel_thumbs{display:flex;justify-content:flex-start;height:80px;margin-left:auto;margin-right:auto}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container{padding:0 22px}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container .content-wrapper{padding:0}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb{opacity:1;cursor:pointer;transition:all .2s ease;padding:4px;border:1px solid #f6f5f4}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb.active,#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:hover{border-color:#22313c}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:not(:last-child){margin-right:10px}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb img{height:68px}.image-modal{position:fixed;inset:0;background:rgba(0,0,0,.8);display:flex;align-items:center;justify-content:center;z-index:1000}.image-modal__content{position:relative;max-width:90vw;max-height:90vh}.image-modal__content img{max-width:90vw;max-height:90vh;-o-object-fit:contain;object-fit:contain;display:block}.image-modal__close{position:fixed;top:15px;right:30px;background:transparent;border:none;color:#fff;font-size:60px;line-height:1;cursor:pointer}@media screen and (max-width: 650px){#product_page_carousel_thumbs{height:57px!important}#product_page_carousel_thumbs .carousel-thumb img{height:50px!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"]
|
|
1527
1597
|
},] }
|
|
1528
1598
|
];
|
|
1529
1599
|
ImageCarouselComponent.ctorParameters = () => [
|
|
@@ -1534,6 +1604,7 @@ ImageCarouselComponent.ctorParameters = () => [
|
|
|
1534
1604
|
];
|
|
1535
1605
|
ImageCarouselComponent.propDecorators = {
|
|
1536
1606
|
carousel: [{ type: ViewChild, args: ['carousel', { read: ElementRef },] }],
|
|
1607
|
+
onEsc: [{ type: HostListener, args: ['document:keydown.escape',] }],
|
|
1537
1608
|
showRefresh: [{ type: Input }],
|
|
1538
1609
|
images: [{ type: Input }],
|
|
1539
1610
|
handleWindowResize: [{ type: HostListener, args: ['window:resize',] }],
|
|
@@ -1782,11 +1853,12 @@ ProductPriceModule.decorators = [
|
|
|
1782
1853
|
];
|
|
1783
1854
|
|
|
1784
1855
|
class ProductAddtocartComponent {
|
|
1785
|
-
constructor(iconCache, _ioneControllerService, _appEventService, _settingsService) {
|
|
1856
|
+
constructor(iconCache, _ioneControllerService, _appEventService, _settingsService, _productConnectorAdapterService) {
|
|
1786
1857
|
this.iconCache = iconCache;
|
|
1787
1858
|
this._ioneControllerService = _ioneControllerService;
|
|
1788
1859
|
this._appEventService = _appEventService;
|
|
1789
1860
|
this._settingsService = _settingsService;
|
|
1861
|
+
this._productConnectorAdapterService = _productConnectorAdapterService;
|
|
1790
1862
|
this.icon = IconEnum;
|
|
1791
1863
|
this.createFrozenArticle = true;
|
|
1792
1864
|
this.configurable = false;
|
|
@@ -1826,9 +1898,14 @@ class ProductAddtocartComponent {
|
|
|
1826
1898
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1827
1899
|
if (this.createFrozenArticle) {
|
|
1828
1900
|
if (this.article.goodType === 'B') {
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1901
|
+
if (this.article.isConfigurable) {
|
|
1902
|
+
const article = yield this._getJSONFromArticleObject({ article: this.article, quantity: quantity });
|
|
1903
|
+
if (article) {
|
|
1904
|
+
this._appEventService.onAddToCart.next({ article: article, quantity: quantity });
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
else {
|
|
1908
|
+
yield this._handleGeneratedArticleDirectly(quantity);
|
|
1832
1909
|
}
|
|
1833
1910
|
}
|
|
1834
1911
|
else {
|
|
@@ -1845,8 +1922,15 @@ class ProductAddtocartComponent {
|
|
|
1845
1922
|
}
|
|
1846
1923
|
}
|
|
1847
1924
|
else {
|
|
1848
|
-
|
|
1849
|
-
|
|
1925
|
+
if (this.article.goodType === 'B') {
|
|
1926
|
+
if (!this.article.isConfigurable) {
|
|
1927
|
+
yield this._handleGeneratedArticleDirectly(quantity);
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
else {
|
|
1931
|
+
const article = this._ioneControllerService.convertArticleFullObjectToArticleExtended(this.article);
|
|
1932
|
+
this._appEventService.onAddToCart.next({ article: article, quantity: quantity });
|
|
1933
|
+
}
|
|
1850
1934
|
}
|
|
1851
1935
|
});
|
|
1852
1936
|
}
|
|
@@ -1855,6 +1939,21 @@ class ProductAddtocartComponent {
|
|
|
1855
1939
|
this._appEventService.onAddToQuote.next(yield this._getJSONFromArticleObject({ article: this.article, quantity: quantity }));
|
|
1856
1940
|
});
|
|
1857
1941
|
}
|
|
1942
|
+
_handleGeneratedArticleDirectly(quantity) {
|
|
1943
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1944
|
+
const generatedGoodId = yield this._getGeneratedArtDirectly(this.article.goodId);
|
|
1945
|
+
if (generatedGoodId) {
|
|
1946
|
+
const articleFull = yield this._productConnectorAdapterService.getArticleFullObject(generatedGoodId, true);
|
|
1947
|
+
const article = this._ioneControllerService.convertArticleFullObjectToArticleExtended(articleFull);
|
|
1948
|
+
this._appEventService.onAddToCart.next({ article: article, quantity: quantity });
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
_getGeneratedArtDirectly(goodId) {
|
|
1953
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1954
|
+
return yield this._ioneControllerService.getGeneratedArtDirectly(goodId, true);
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1858
1957
|
_getJSONFromArticleObject(article) {
|
|
1859
1958
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1860
1959
|
const configuratorStatistics = new ConfiguratorStatisticsEnvironment();
|
|
@@ -1909,7 +2008,8 @@ ProductAddtocartComponent.ctorParameters = () => [
|
|
|
1909
2008
|
{ type: IconCacheService },
|
|
1910
2009
|
{ type: ProductConnectorService },
|
|
1911
2010
|
{ type: ProductEventService },
|
|
1912
|
-
{ type: ProductSettingsService }
|
|
2011
|
+
{ type: ProductSettingsService },
|
|
2012
|
+
{ type: ProductConnectorAdapterService }
|
|
1913
2013
|
];
|
|
1914
2014
|
ProductAddtocartComponent.propDecorators = {
|
|
1915
2015
|
addToCartButton: [{ type: ViewChild, args: ['addtocartbutton', { read: ElementRef },] }],
|
|
@@ -2300,7 +2400,7 @@ class ProductInfoTabsComponent {
|
|
|
2300
2400
|
this.updateHeight(tabIndex);
|
|
2301
2401
|
}
|
|
2302
2402
|
updateHeight(tabIndex) {
|
|
2303
|
-
if (this.tabContent.nativeElement.children.length > 0) {
|
|
2403
|
+
if (this.tabContent && this.tabContent.nativeElement.children.length > 0) {
|
|
2304
2404
|
if (this.tabContent.nativeElement.children[tabIndex] !== undefined) {
|
|
2305
2405
|
this.activeTabHeight = this.tabContent.nativeElement.children[tabIndex].offsetHeight;
|
|
2306
2406
|
}
|