Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Configurable media component #19067

Merged
merged 62 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
2c46d51
changes
rmch91 Jul 23, 2024
1fd0a9a
implementation of new media formats
rmch91 Jul 23, 2024
d0afd14
add map to config
rmch91 Jul 24, 2024
176f055
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Jul 24, 2024
f622e76
removed interface
rmch91 Jul 24, 2024
f4d4a60
refactor
rmch91 Jul 24, 2024
fe2de44
fix sonar issues
rmch91 Jul 24, 2024
87563cb
changes
rmch91 Jul 24, 2024
8359060
changes
rmch91 Jul 24, 2024
02f8ac5
unit tests for media component
rmch91 Jul 25, 2024
7a22839
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Jul 25, 2024
5f87a0f
tests and changes
rmch91 Jul 30, 2024
fc9989c
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Jul 30, 2024
df8fea8
add unit tests
rmch91 Jul 30, 2024
ef2c042
changes
rmch91 Jul 30, 2024
3b608ce
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Aug 1, 2024
9850b07
changes
rmch91 Aug 1, 2024
8f682a6
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Aug 1, 2024
c6f0135
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Sep 4, 2024
6dedfa2
changes
rmch91 Sep 5, 2024
5608652
some adjustements
rmch91 Sep 5, 2024
df89833
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Sep 5, 2024
16bf99c
fix tests
rmch91 Sep 6, 2024
132164f
add tests for width and height
rmch91 Sep 6, 2024
5eaa0c4
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Sep 6, 2024
d8b745b
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Oct 9, 2024
64fe126
changes after review
rmch91 Oct 11, 2024
d224542
changes
rmch91 Oct 11, 2024
5c6a462
change unit tests
rmch91 Oct 14, 2024
06fbe15
changes
rmch91 Oct 14, 2024
df1fa48
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Oct 14, 2024
1d13aa2
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Oct 14, 2024
dc61ba6
Change default config
rmch91 Oct 15, 2024
1801f06
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Oct 15, 2024
8e39174
changes
rmch91 Oct 15, 2024
3564192
fix
rmch91 Oct 15, 2024
7e2e348
changes after review
rmch91 Oct 15, 2024
9ecab23
changes
rmch91 Oct 15, 2024
321e272
Merge branch 'develop' into feat/CXSPA-7700
pawelfras Oct 15, 2024
2da112c
Merge branch 'develop' into feat/CXSPA-7700
pawelfras Oct 16, 2024
2437bb0
changes after review
rmch91 Oct 16, 2024
27241eb
fix to pr
rmch91 Oct 16, 2024
cc30ef3
Merge remote-tracking branch 'origin/feat/CXSPA-7700' into feat/CXSPA…
rmch91 Oct 16, 2024
a04ece0
Merge remote-tracking branch 'origin/develop' into feat/CXSPA-7700
rmch91 Oct 16, 2024
d8adfdb
add elementType img
rmch91 Oct 16, 2024
a9e8f2c
Merge branch 'develop' into feat/CXSPA-7700
pawelfras Oct 17, 2024
780d358
Merge remote-tracking branch 'origin/feat/CXSPA-7700' into feat/CXSPA…
rmch91 Oct 17, 2024
b7e77e5
change e2e
rmch91 Oct 17, 2024
6364313
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Oct 17, 2024
7c7068b
fix units
rmch91 Oct 17, 2024
0641aaf
fix cds test
rmch91 Oct 17, 2024
aebfd58
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Oct 17, 2024
bdbd15e
fix tests
rmch91 Oct 17, 2024
28d31c9
fix imports
rmch91 Oct 17, 2024
7c10aa3
Revert "fix imports"
rmch91 Oct 17, 2024
deb1a30
Revert "fix tests"
rmch91 Oct 17, 2024
ae40973
Revert "fix cds test"
rmch91 Oct 17, 2024
01e885c
Revert "fix units"
rmch91 Oct 17, 2024
d29bbcb
Revert "add elementType img"
rmch91 Oct 17, 2024
6e37017
change default elementType to img
rmch91 Oct 17, 2024
da4681f
Merge branch 'develop' into feat/CXSPA-7700
rmch91 Oct 17, 2024
1af972d
Merge branch 'develop' into feat/CXSPA-7700
pawelfras Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, Input, Pipe, PipeTransform } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import {
FeatureConfigService,
I18nTestingModule,
ImageType,
Product,
Expand Down Expand Up @@ -64,6 +65,7 @@ describe('ConfiguratorOverviewBundleAttributeComponent', () => {
let component: ConfiguratorOverviewBundleAttributeComponent;
let fixture: ComponentFixture<ConfiguratorOverviewBundleAttributeComponent>;
let htmlElem: HTMLElement;
let featureConfigService: FeatureConfigService;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
Expand All @@ -73,7 +75,10 @@ describe('ConfiguratorOverviewBundleAttributeComponent', () => {
MockConfiguratorPriceComponent,
MockNumericPipe,
],
providers: [{ provide: ProductService, useClass: MockProductService }],
providers: [
{ provide: ProductService, useClass: MockProductService },
FeatureConfigService,
],
}).compileComponents();
}));

Expand All @@ -83,6 +88,7 @@ describe('ConfiguratorOverviewBundleAttributeComponent', () => {
);
component = fixture.componentInstance;
htmlElem = fixture.nativeElement;
featureConfigService = TestBed.inject(FeatureConfigService);
});

beforeEach(() => {
Expand Down Expand Up @@ -142,6 +148,8 @@ describe('ConfiguratorOverviewBundleAttributeComponent', () => {

describe('product image', () => {
it('should be visible if primary', () => {
spyOn(featureConfigService, 'isEnabled').and.returnValue(true);

product$.next(mockProduct);

fixture.detectChanges();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,35 @@ export interface FeatureTogglesInterface {
* in the future together with this feature toggle.
*/
allPageMetaResolversEnabledInCsr?: boolean;

/**
* When enabled, allows to provide extended formats and media queries for <picture> element if used in MediaComponent.
*
* Important: After activation default HTML element in MediaComponent will be `<img>`
* Only BannerComponent has passed `'picture'` value. If you need to use `<picture>` HTML element
* you need to pass `[elementType]="'picture'"` to `<cx-media>`
*
* For proper work requires `pictureElementFormats` provided in media config:
* ```ts
* provideConfig({
* pictureElementFormats: {
* mediaQueries: {
* 'max-width': '767px',
* ...
* },
* width: 50,
* height: 50,
* },
* })
* ```
*
* After activating this toggle, new inputs in `MediaComponent` — specifically
* `width`, `height`, and `sizes` — will be passed to the template as HTML attributes.
*
* Toggle activates `@Input() elementType: 'img' | 'picture' = 'img'` in `MediaComponent`
*
*/
useExtendedMediaComponentConfiguration?: boolean;
}

export const defaultFeatureToggles: Required<FeatureTogglesInterface> = {
Expand Down Expand Up @@ -738,4 +767,5 @@ export const defaultFeatureToggles: Required<FeatureTogglesInterface> = {
enableConsecutiveCharactersPasswordRequirement: false,
enablePasswordsCannotMatchInPasswordUpdateForm: false,
allPageMetaResolversEnabledInCsr: false,
useExtendedMediaComponentConfiguration: false,
};
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ export function navigateToPDPInCustomerInterest(productCode: string) {
cy.get('.cx-product-interests-product-item').within(() => {
cy.get('.cx-code').should('contain', productCode);
cy.get(
'.cx-product-interests-product-image-link > .is-initialized > picture'
'.cx-product-interests-product-image-link > .is-initialized > img'
).click();
});
}
Expand Down
12 changes: 2 additions & 10 deletions projects/storefrontapp/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,13 @@ import { translationChunksConfig, translations } from '@spartacus/assets';
import {
I18nConfig,
OccConfig,
provideConfig,
RoutingConfig,
TestConfigModule,
provideConfig,
} from '@spartacus/core';
import { StoreFinderConfig } from '@spartacus/storefinder/core';
import { GOOGLE_MAPS_DEVELOPMENT_KEY_CONFIG } from '@spartacus/storefinder/root';
import {
AppRoutingModule,
StorefrontComponent,
USE_LEGACY_MEDIA_COMPONENT,
} from '@spartacus/storefront';
import { AppRoutingModule, StorefrontComponent } from '@spartacus/storefront';
import { environment } from '../environments/environment';
import { TestOutletModule } from '../test-outlets/test-outlet.module';
import { SpartacusModule } from './spartacus/spartacus.module';
Expand Down Expand Up @@ -94,10 +90,6 @@ if (!environment.production) {
// without a key, for development or demo purposes.
googleMaps: { apiKey: GOOGLE_MAPS_DEVELOPMENT_KEY_CONFIG },
}),
{
provide: USE_LEGACY_MEDIA_COMPONENT,
useValue: false,
},
],
bootstrap: [StorefrontComponent],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ if (environment.cpq) {
enableConsecutiveCharactersPasswordRequirement: true,
enablePasswordsCannotMatchInPasswordUpdateForm: true,
allPageMetaResolversEnabledInCsr: true,
useExtendedMediaComponentConfiguration: true,
};
return appFeatureToggles;
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
>
</cx-generic-link>
<p class="headline" *ngIf="data.headline" [innerHTML]="data.headline"></p>
<cx-media [container]="getImage(data)"></cx-media>
<cx-media
*cxFeature="'useExtendedMediaComponentConfiguration'"
[container]="getImage(data)"
[elementType]="'picture'"
></cx-media>
<cx-media
*cxFeature="'!useExtendedMediaComponentConfiguration'"
[container]="getImage(data)"
></cx-media>
<p class="content" *ngIf="data.content" [innerHTML]="data.content"></p>
</ng-container>
</ng-container>
Expand All @@ -21,14 +29,30 @@
[target]="getTarget(data)"
>
<p class="headline" *ngIf="data.headline" [innerHTML]="data.headline"></p>
<cx-media [container]="getImage(data)"></cx-media>
<cx-media
*cxFeature="'useExtendedMediaComponentConfiguration'"
[container]="getImage(data)"
[elementType]="'picture'"
></cx-media>
<cx-media
*cxFeature="'!useExtendedMediaComponentConfiguration'"
[container]="getImage(data)"
></cx-media>
<p class="content" *ngIf="data.content" [innerHTML]="data.content"></p>
</cx-generic-link>
</ng-container>
<ng-container *ngIf="!routerLink">
<div class="no-link">
<p class="headline" *ngIf="data.headline" [innerHTML]="data.headline"></p>
<cx-media [container]="getImage(data)"></cx-media>
<cx-media
*cxFeature="'useExtendedMediaComponentConfiguration'"
[container]="getImage(data)"
[elementType]="'picture'"
></cx-media>
<cx-media
*cxFeature="'!useExtendedMediaComponentConfiguration'"
[container]="getImage(data)"
></cx-media>
<p class="content" *ngIf="data.content" [innerHTML]="data.content"></p>
</div>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
SemanticPathService,
UrlCommand,
} from '@spartacus/core';
import { MockFeatureDirective } from 'projects/storefrontlib/shared/test/mock-feature-directive';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { CmsComponentData } from '../../../cms-structure/page/model/cms-component-data';
import { GenericLinkComponent } from '../../../shared/components/generic-link/generic-link.component';
Expand Down Expand Up @@ -81,7 +82,12 @@ describe('BannerComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, FeaturesConfigModule],
declarations: [BannerComponent, MockMediaComponent, GenericLinkComponent],
declarations: [
BannerComponent,
MockMediaComponent,
GenericLinkComponent,
MockFeatureDirective,
],
providers: [
{
provide: CmsComponentData,
Expand Down
15 changes: 15 additions & 0 deletions projects/storefrontlib/recipes/config/default-media.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,19 @@ export const mediaConfig: MediaConfig = {
product: { width: 284 },
zoom: { width: 515 },
},
pictureElementFormats: {
mobile: {
mediaQueries: '(max-width: 767px)',
},
tablet: {
mediaQueries: '(min-width: 768px) and (max-width: 1024px)',
},
desktop: {
mediaQueries: '(min-width: 1025px) and (max-width: 1439px)',
},
widescreen: {
mediaQueries: '(min-width: 1440px)',
},
},
pictureFormatsOrder: ['widescreen', 'desktop', 'tablet', 'mobile'],
};
111 changes: 80 additions & 31 deletions projects/storefrontlib/shared/components/media/media.component.html
Original file line number Diff line number Diff line change
@@ -1,36 +1,85 @@
<ng-container *ngIf="!!media">
<picture *ngIf="media.srcset && !isLegacy; else legacyImgTmp">
<source
*ngFor="
let source of media!.srcset! | cxMediaSources;
trackBy: trackByMedia
<ng-container *cxFeature="'useExtendedMediaComponentConfiguration'">
<picture
*ngIf="
!!media?.sources?.length && elementType !== 'img';
else imageElementTmp
"
[srcset]="source.srcset"
[media]="source.media"
/>
>
<source
*ngFor="let source of media.sources; trackBy: trackByMedia"
[media]="source.media"
[srcset]="source.srcset"
[attr.width]="source.width"
[attr.height]="source.height"
/>

<img
[loading]="loading"
[alt]="media.alt"
[title]="media.alt"
[src]="media.src"
[attr.role]="media.role"
(load)="loadHandler()"
(error)="errorHandler()"
/>
</picture>
<img
[loading]="loading"
[alt]="media.alt"
[title]="media.alt"
[src]="media.src"
[attr.role]="media.role"
[attr.width]="width"
[attr.height]="height"
[attr.sizes]="sizes"
(load)="loadHandler()"
(error)="errorHandler()"
/>
</picture>

<ng-template #legacyImgTmp>
<img
*ngIf="media.src"
[loading]="loading"
[alt]="media.alt"
[title]="media.alt"
[src]="media.src"
[srcset]="media?.srcset || media.src"
[attr.role]="media.role"
(load)="loadHandler()"
(error)="errorHandler()"
/>
</ng-template>
<ng-template #imageElementTmp>
<img
*ngIf="media.src"
[loading]="loading"
[alt]="media.alt"
[title]="media.alt"
[src]="media.src"
[srcset]="media.srcset || media.src"
[attr.role]="media.role"
[attr.width]="width"
[attr.height]="height"
[attr.sizes]="sizes"
(load)="loadHandler()"
(error)="errorHandler()"
/>
</ng-template>
</ng-container>

<ng-container *cxFeature="'!useExtendedMediaComponentConfiguration'">
<picture *ngIf="media.srcset && !isLegacy; else legacyImgTmp">
<source
*ngFor="
let source of media!.srcset! | cxMediaSources;
trackBy: trackByMedia
"
[srcset]="source.srcset"
[media]="source.media"
/>

<img
[loading]="loading"
[alt]="media.alt"
[title]="media.alt"
[src]="media.src"
[attr.role]="media.role"
(load)="loadHandler()"
(error)="errorHandler()"
/>
</picture>

<ng-template #legacyImgTmp>
<img
*ngIf="media.src"
[loading]="loading"
[alt]="media.alt"
[title]="media.alt"
[src]="media.src"
[srcset]="media?.srcset || media.src"
[attr.role]="media.role"
(load)="loadHandler()"
(error)="errorHandler()"
/>
</ng-template>
</ng-container>
</ng-container>
Loading
Loading