diff --git a/projects/core/src/model/cms.model.ts b/projects/core/src/model/cms.model.ts
index 8b627ba7403..1468ac5564d 100644
--- a/projects/core/src/model/cms.model.ts
+++ b/projects/core/src/model/cms.model.ts
@@ -25,6 +25,10 @@ export interface CmsComponent {
styleClasses?: string;
}
+export interface CmsComponentWithChildren extends CmsComponent {
+ children?: string;
+}
+
export enum PageType {
CONTENT_PAGE = 'ContentPage',
PRODUCT_PAGE = 'ProductPage',
diff --git a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.html b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.html
index 6e6d233ac29..4c28b14245a 100644
--- a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.html
+++ b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.html
@@ -1,3 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.spec.ts b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.spec.ts
index 3b3ba98838a..f4160a51dd7 100644
--- a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.spec.ts
+++ b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.spec.ts
@@ -1,10 +1,41 @@
-import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
-import { Product } from '@spartacus/core';
-import { Observable, of } from 'rxjs';
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { CmsComponentWithChildren, CmsService, Product } from '@spartacus/core';
+import { BehaviorSubject, Observable, of } from 'rxjs';
+import { CmsComponentData } from '../../../../cms-structure/page/model/cms-component-data';
import { CurrentProductService } from '../../current-product.service';
import { ProductDetailsTabComponent } from './product-details-tab.component';
const mockProduct: Product = { name: 'mockProduct' };
+const mockCmsComponentWithChildren: CmsComponentWithChildren = {
+ name: 'Product Details Tab',
+ typeCode: 'CMSFlexComponent',
+ uid: 'testUid',
+ children: 'TestPDFComponent',
+};
+
+const mockCmsComponentWithNoChildren: CmsComponentWithChildren = {
+ name: 'Product Details Tab',
+ typeCode: 'CMSFlexComponent',
+ uid: 'testUid',
+};
+
+const mockPDFComponent = {
+ ui: 'TestPDFComponent',
+ uuid: 'PDFComponent',
+ typeCode: 'PDFDocumentComponent',
+ name: 'TestPDFName',
+ container: false,
+ pdfFile: {
+ code: 'test-pdf',
+ mime: 'application/pdf',
+ url: '/medias/test.pdf?context=bWFzdGVyfGl',
+ },
+ synchronizationBlocked: false,
+ title: 'ProductDetails',
+ parents: 'ProductDetailsTabComponent',
+ height: '200',
+ modifiedTime: '2022-05-20T13:07:22.277Z',
+};
class MockCurrentProductService {
getProduct(): Observable {
@@ -12,6 +43,25 @@ class MockCurrentProductService {
}
}
+const data$: BehaviorSubject = new BehaviorSubject(
+ mockCmsComponentWithChildren
+);
+
+class MockCmsComponentData {
+ get data$(): Observable {
+ return data$.asObservable();
+ }
+}
+
+class MockCmsService {
+ getComponentData(component: string): Observable {
+ if (component === 'TestPDFComponent') {
+ return of(mockPDFComponent);
+ }
+ return of(null);
+ }
+}
+
describe('ProductDetailsTabComponent', () => {
let productDetailsTabComponent: ProductDetailsTabComponent;
let fixture: ComponentFixture;
@@ -25,6 +75,14 @@ describe('ProductDetailsTabComponent', () => {
provide: CurrentProductService,
useClass: MockCurrentProductService,
},
+ {
+ provide: CmsComponentData,
+ useClass: MockCmsComponentData,
+ },
+ {
+ provide: CmsService,
+ useClass: MockCmsService,
+ },
],
}).compileComponents();
})
@@ -41,10 +99,47 @@ describe('ProductDetailsTabComponent', () => {
it('should get product', () => {
productDetailsTabComponent.ngOnInit();
- let result: Product;
+ let result: Product | null | undefined;
productDetailsTabComponent.product$.subscribe(
(product) => (result = product)
);
expect(result).toEqual(mockProduct);
});
+
+ it('should get undefined children when child cmsComponents are unknown', () => {
+ let result: any[] | undefined;
+ data$.next({
+ ...mockCmsComponentWithChildren,
+ children: 'testCpntOne testCpntTwo',
+ });
+
+ productDetailsTabComponent.children$
+ .subscribe((children) => (result = children))
+ .unsubscribe();
+ expect(result).toEqual([undefined, undefined]);
+ });
+
+ it('should get children containing cms PDFComponent', () => {
+ let result: any[] | undefined;
+ data$.next({ ...mockCmsComponentWithChildren });
+ productDetailsTabComponent.children$
+ .subscribe((children) => (result = children))
+ .unsubscribe();
+
+ expect(result).toContain({
+ ...mockPDFComponent,
+ flexType: mockPDFComponent.typeCode,
+ });
+ });
+
+ it('should get undefined children when cmsComponent has no children property', () => {
+ data$.next({
+ ...mockCmsComponentWithNoChildren,
+ });
+ let result: any[] | undefined;
+ productDetailsTabComponent.children$
+ .subscribe((children) => (result = children))
+ .unsubscribe();
+ expect(result).toEqual([undefined]);
+ });
});
diff --git a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.ts b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.ts
index 9726cb0b9a1..4beed11a083 100644
--- a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.ts
+++ b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.component.ts
@@ -1,6 +1,8 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
-import { Product } from '@spartacus/core';
-import { Observable } from 'rxjs';
+import { CmsComponentWithChildren, CmsService, Product } from '@spartacus/core';
+import { combineLatest, Observable } from 'rxjs';
+import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
+import { CmsComponentData } from '../../../../cms-structure/page/model/cms-component-data';
import { CurrentProductService } from '../../current-product.service';
@Component({
@@ -11,7 +13,35 @@ import { CurrentProductService } from '../../current-product.service';
export class ProductDetailsTabComponent implements OnInit {
product$: Observable;
- constructor(protected currentProductService: CurrentProductService) {}
+ constructor(
+ protected currentProductService: CurrentProductService,
+ protected componentData: CmsComponentData,
+ protected cmsService: CmsService
+ ) {}
+ children$: Observable = this.componentData.data$.pipe(
+ switchMap((data) =>
+ combineLatest(
+ (data?.children ?? '').split(' ').map((component) =>
+ this.cmsService.getComponentData(component).pipe(
+ distinctUntilChanged(),
+ map((child) => {
+ if (!child) {
+ return undefined;
+ }
+ if (!child.flexType) {
+ child = {
+ ...child,
+ flexType: child.typeCode,
+ };
+ }
+
+ return child;
+ })
+ )
+ )
+ )
+ )
+ );
ngOnInit() {
this.product$ = this.currentProductService.getProduct();
diff --git a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.module.ts b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.module.ts
index 7768625582f..a0a7d2f8321 100644
--- a/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.module.ts
+++ b/projects/storefrontlib/cms-components/product/product-tabs/product-details-tab/product-details-tab.module.ts
@@ -1,11 +1,12 @@
-import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
-
+import { NgModule } from '@angular/core';
import { CmsConfig, provideDefaultConfig } from '@spartacus/core';
+import { OutletModule } from './../../../../cms-structure/outlet/outlet.module';
+import { PageComponentModule } from './../../../../cms-structure/page/component/page-component.module';
import { ProductDetailsTabComponent } from './product-details-tab.component';
@NgModule({
- imports: [CommonModule],
+ imports: [CommonModule, PageComponentModule, OutletModule],
providers: [
provideDefaultConfig({
cmsComponents: {
diff --git a/projects/storefrontstyles/scss/components/content/pdf/_pdf.scss b/projects/storefrontstyles/scss/components/content/pdf/_pdf.scss
index 6753cb86e42..cda5226ed9e 100644
--- a/projects/storefrontstyles/scss/components/content/pdf/_pdf.scss
+++ b/projects/storefrontstyles/scss/components/content/pdf/_pdf.scss
@@ -1,14 +1,15 @@
%cx-pdf {
.pdf-container {
- padding: 0.938rem;
+ padding-top: 0.938rem;
font-size: var(--cx-font-size, 0.875rem);
a {
color: var(--cx-color-text);
line-height: 1.1875rem;
text-decoration: underline;
+ font-weight: 600;
}
cx-icon {
- margin-inline-start: 0.625rem;
+ margin-inline-start: 0.3rem;
background-color: transparent;
border: none;
text-decoration: none;