Skip to content

Commit

Permalink
feat: add support for CMS component "Product List (Filter)" (#673)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eisie96 authored and shauke committed Jun 10, 2021
1 parent 8df9599 commit fbc5e3e
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/app/core/facades/cms.facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { Observable, combineLatest } from 'rxjs';
import { delay, filter, map, switchMap, tap } from 'rxjs/operators';

import { CallParameters } from 'ish-core/models/call-parameters/call-parameters.model';
import { CategoryHelper } from 'ish-core/models/category/category.helper';
import { getContentInclude, loadContentInclude } from 'ish-core/store/content/includes';
import { getContentPageTree, loadContentPageTree } from 'ish-core/store/content/page-tree';
import { getContentPagelet } from 'ish-core/store/content/pagelets';
import { getContentPageLoading, getSelectedContentPage } from 'ish-core/store/content/pages';
import { getParametersProductList, loadParametersProductListFilter } from 'ish-core/store/content/parameters';
import { getViewContext, loadViewContextEntrypoint } from 'ish-core/store/content/viewcontexts';
import { getPGID } from 'ish-core/store/customer/user';
import { whenTruthy } from 'ish-core/utils/operators';
import { URLFormParams } from 'ish-core/utils/url-form-params';
import { SfeAdapterService } from 'ish-shared/cms/sfe-adapter/sfe-adapter.service';
import { SfeMapper } from 'ish-shared/cms/sfe-adapter/sfe.mapper';

Expand Down Expand Up @@ -50,4 +53,39 @@ export class CMSFacade {
this.store.dispatch(loadContentPageTree({ rootId, depth }));
return this.store.pipe(select(getContentPageTree(rootId)));
}

parameterProductListFilter$(categoryId?: string, productFilter?: string, scope?: string, amount?: number) {
const listConfiguration = this.getProductListConfiguration(categoryId, productFilter, scope, amount);
this.store.dispatch(
loadParametersProductListFilter({
id: listConfiguration.id,
searchParameter: listConfiguration.searchParameter,
amount,
})
);
return this.store.pipe(select(getParametersProductList(listConfiguration.id)));
}

private getProductListConfiguration(
categoryId?: string,
productFilter?: string,
scope?: string,
amount?: number
): { id: string; searchParameter: URLFormParams } {
let id = '';
const searchParameter: URLFormParams = {};

id = categoryId ? `${id}@${categoryId}` : id;
id = productFilter ? `${id}@${productFilter}` : id;
id = scope ? `${id}@${scope}` : id;
id = amount ? `${id}@${amount}` : id;

if (categoryId && scope !== 'Global') {
searchParameter.category = [CategoryHelper.getCategoryPath(categoryId)];
}

searchParameter.productFilter = productFilter ? [productFilter] : ['fallback_searchquerydefinition'];

return { id, searchParameter };
}
}
9 changes: 9 additions & 0 deletions src/app/shared/cms/cms.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CMSFreestyleComponent } from './components/cms-freestyle/cms-freestyle.
import { CMSImageEnhancedComponent } from './components/cms-image-enhanced/cms-image-enhanced.component';
import { CMSImageComponent } from './components/cms-image/cms-image.component';
import { CMSLandingPageComponent } from './components/cms-landing-page/cms-landing-page.component';
import { CMSProductListFilterComponent } from './components/cms-product-list-filter/cms-product-list-filter.component';
import { CMSProductListComponent } from './components/cms-product-list/cms-product-list.component';
import { CMSStandardPageComponent } from './components/cms-standard-page/cms-standard-page.component';
import { CMSStaticPageComponent } from './components/cms-static-page/cms-static-page.component';
Expand Down Expand Up @@ -73,6 +74,14 @@ import { SfeAdapterService } from './sfe-adapter/sfe-adapter.service';
},
multi: true,
},
{
provide: CMS_COMPONENT,
useValue: {
definitionQualifiedName: 'app_sf_base_cm:component.common.productListFilter.pagelet2-Component',
class: CMSProductListFilterComponent,
},
multi: true,
},
{
provide: CMS_COMPONENT,
useValue: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<ng-container *ngIf="productSKUs$ | async as productSKUs">
<div *ngIf="productSKUs?.length" class="product-list-container" [ngClass]="pagelet.stringParam('CSSClass')">
<h2 *ngIf="pagelet.stringParam('Title')">{{ pagelet.stringParam('Title') }}</h2>
<ish-products-list
[productSKUs]="productSKUs"
[listStyle]="pagelet.stringParam('ListStyle')"
[slideItems]="pagelet.numberParam('SlideItems')"
[listItemStyle]="pagelet.stringParam('ListItemStyle')"
[listItemCSSClass]="pagelet.stringParam('ListItemCSSClass')"
>
</ish-products-list>
</div>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MockComponent } from 'ng-mocks';
import { of } from 'rxjs';
import { anyNumber, instance, mock, when } from 'ts-mockito';

import { CMSFacade } from 'ish-core/facades/cms.facade';
import { ShoppingFacade } from 'ish-core/facades/shopping.facade';
import { ContentPagelet } from 'ish-core/models/content-pagelet/content-pagelet.model';
import { createContentPageletView } from 'ish-core/models/content-view/content-view.model';
import { ProductsListComponent } from 'ish-shared/components/product/products-list/products-list.component';

import { CMSProductListFilterComponent } from './cms-product-list-filter.component';

describe('Cms Product List Filter Component', () => {
let component: CMSProductListFilterComponent;
let fixture: ComponentFixture<CMSProductListFilterComponent>;
let element: HTMLElement;
let cmsFacade: CMSFacade;
let shoppingFacade: ShoppingFacade;
let pagelet: ContentPagelet;

beforeEach(async () => {
cmsFacade = mock(CMSFacade);
shoppingFacade = mock(ShoppingFacade);

await TestBed.configureTestingModule({
declarations: [CMSProductListFilterComponent, MockComponent(ProductsListComponent)],
providers: [
{ provide: CMSFacade, useFactory: () => instance(cmsFacade) },
{ provide: ShoppingFacade, useFactory: () => instance(shoppingFacade) },
],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(CMSProductListFilterComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;

pagelet = {
definitionQualifiedName: 'fq',
id: 'id',
displayName: 'name',
domain: 'domain',
configurationParameters: {
ListStyle: 'Carousel',
MaxNumberOfProducts: 6,
ShowViewAll: 'true',
SlideItems: 4,
Scope: 'GlobalScope',
Filter: 'top_seller_products',
ListItemStyle: 'tile',
Title: 'Filter Products Pagelet',
CSSClass: 'container',
ListItemCSSClass: 'col-12 col-sm-6 col-lg-3',
},
};
component.pagelet = createContentPageletView(pagelet);
});

it('should be created', () => {
expect(component).toBeTruthy();
expect(element).toBeTruthy();
expect(() => fixture.detectChanges()).not.toThrow();
});

describe('getProductSKUs$', () => {
beforeEach(() => {
when(
cmsFacade.parameterProductListFilter$('categoryId', 'top_seller_products', 'GlobalScope', anyNumber())
).thenReturn(of(['id-1', 'id-2', 'id-3']));
when(shoppingFacade.selectedCategoryId$).thenReturn(of('categoryId'));
});

it('should get all available products for given product filter', done => {
component.pagelet = createContentPageletView({
...pagelet,
configurationParameters: {
...pagelet.configurationParameters,
MaxNumberOfProducts: 6,
},
});

component.ngOnChanges();

component.productSKUs$.subscribe(productSKUs => {
expect(productSKUs).toHaveLength(3);
expect(productSKUs).toMatchInlineSnapshot(`
Array [
"id-1",
"id-2",
"id-3",
]
`);
done();
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';

import { CMSFacade } from 'ish-core/facades/cms.facade';
import { ShoppingFacade } from 'ish-core/facades/shopping.facade';
import { ContentPageletView } from 'ish-core/models/content-view/content-view.model';
import { CMSComponent } from 'ish-shared/cms/models/cms-component/cms-component.model';

@Component({
selector: 'ish-cms-product-list-filter',
templateUrl: './cms-product-list-filter.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CMSProductListFilterComponent implements CMSComponent, OnChanges {
@Input() pagelet: ContentPageletView;

productSKUs$: Observable<string[]>;

constructor(private cmsFacade: CMSFacade, private shoppingFacade: ShoppingFacade) {}

ngOnChanges() {
if (this.pagelet.hasParam('Filter')) {
this.productSKUs$ = this.getProductSKUs$();
}
}

getProductSKUs$(): Observable<string[]> {
return this.shoppingFacade.selectedCategoryId$.pipe(
switchMap(categoryId =>
this.cmsFacade.parameterProductListFilter$(
categoryId,
this.pagelet.stringParam('Filter'),
this.pagelet.stringParam('Scope'),
this.pagelet.numberParam('MaxNumberOfProducts')
)
)
);
}
}
2 changes: 2 additions & 0 deletions src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { CMSFreestyleComponent } from './cms/components/cms-freestyle/cms-freest
import { CMSImageEnhancedComponent } from './cms/components/cms-image-enhanced/cms-image-enhanced.component';
import { CMSImageComponent } from './cms/components/cms-image/cms-image.component';
import { CMSLandingPageComponent } from './cms/components/cms-landing-page/cms-landing-page.component';
import { CMSProductListFilterComponent } from './cms/components/cms-product-list-filter/cms-product-list-filter.component';
import { CMSProductListComponent } from './cms/components/cms-product-list/cms-product-list.component';
import { CMSStandardPageComponent } from './cms/components/cms-standard-page/cms-standard-page.component';
import { CMSStaticPageComponent } from './cms/components/cms-static-page/cms-static-page.component';
Expand Down Expand Up @@ -171,6 +172,7 @@ const declaredComponents = [
CMSImageEnhancedComponent,
CMSLandingPageComponent,
CMSProductListComponent,
CMSProductListFilterComponent,
CMSStandardPageComponent,
CMSStaticPageComponent,
CMSTextComponent,
Expand Down

0 comments on commit fbc5e3e

Please sign in to comment.