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;