src/converter/teaser/fs-teaser-converter.ts
This class is a factory to create content links from a ExpectedTeaserStructureFromCaas.
Properties |
Methods |
|
constructor(overlayFactory: FsTeaserOverlayFactory)
|
||||||
Parameters :
|
Private addOverlay | |||||||||
addOverlay(area: ImageLinkTemplate | TextLinkTemplate | SearchLinkLinkTemplate | CategoryLinkTemplate | ProductLinkTemplate | ContentLinkTemplate, media: literal type)
|
|||||||||
Parameters :
Returns :
void
|
Private addOverlays | |||||||||
addOverlays(areas: Array
|
|||||||||
Parameters :
Returns :
void
|
Public convert | ||||||
convert(source: ExpectedTeaserStructureFromCaas)
|
||||||
Parameters :
Returns :
TeaserComponentData
|
Private createOverlayPositionData | |||||||||
createOverlayPositionData(area: ImageLinkTemplate | TextLinkTemplate | SearchLinkLinkTemplate | CategoryLinkTemplate | ProductLinkTemplate | ContentLinkTemplate, pictureMetaData: PictureMetaData)
|
|||||||||
Parameters :
|
Private getTeaserSection | ||||||
getTeaserSection(identifier: string)
|
||||||
Type parameters :
|
||||||
Parameters :
Returns :
T | undefined
|
Private processImageMap | |||||||||
processImageMap(imageMap: CmsImageMap, imageAltText?: CmsInputTextFormData)
|
|||||||||
Parameters :
Returns :
void
|
Private setBackgroundImage | ||||||||||||
setBackgroundImage(media: CmsImageMapMedia, resolution: CmsImageMapResolution, imageAltText?: CmsInputTextFormData)
|
||||||||||||
Parameters :
Returns :
void
|
Private setSectionPreviewId |
setSectionPreviewId()
|
Returns :
void
|
Private setTeaserHyperlink | ||||||
setTeaserHyperlink(data: any)
|
||||||
Parameters :
Returns :
void
|
Private source |
Type : ExpectedTeaserStructureFromCaas
|
Private target |
Type : TeaserComponentData
|
import { FsTeaserOverlayFactory } from './fs-teaser-overlay-factory';
import { Injectable, InjectionToken } from '@angular/core';
import { Converter } from '@spartacus/core';
import { nullSafe, toPercentageValue } from 'fs-spartacus-common';
import {
CmsImageMap,
TextLinkTemplate,
CmsInputTextFormData,
ImageLinkTemplate,
ExpectedTeaserStructureFromCaas,
OverlayDimension,
OverlayPosition,
PictureMetaData,
TeaserComponentData,
SearchLinkLinkTemplate,
OverlayText,
OverlayLink,
OverlayImage,
CategoryLinkTemplate,
ProductLinkTemplate,
ContentLinkTemplate,
CmsImageMapMedia,
CmsImageMapResolution,
} from './fs-teaser.model';
/**
* This interface defines a converter for teasers.
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface FsTeaserConverterInterface extends Converter<ExpectedTeaserStructureFromCaas, TeaserComponentData> {}
/**
* The injection token for the {@link FsTeaserConverter}.
*/
export const FsTeaserConverterInjectionToken = new InjectionToken<FsTeaserConverterInterface>('FsTeaserConverter');
const FS_TEASER_IMAGE_MAP_SECTION_TEMPLATE_NAME = 'st_image';
const FS_TEASER_HYPERLINK_SECTION_TEMPLATE_NAME = 'st_link';
const FS_TEASER_IMAGE_ALT_TEXT_SECTION_TEMPLATE_NAME = 'st_alt_text';
const DEFAULT_RESOLUTION = 'ORIGINAL';
/**
* This class is a factory to create content links from a {@link ExpectedTeaserStructureFromCaas}.
*
* @export
* @class FsTeaserConverter
*/
@Injectable({ providedIn: 'root' })
export class FsTeaserConverter implements FsTeaserConverterInterface {
private source: ExpectedTeaserStructureFromCaas;
private target: TeaserComponentData;
constructor(private overlayFactory: FsTeaserOverlayFactory) {}
public convert(source: ExpectedTeaserStructureFromCaas): TeaserComponentData {
// reset the result object with every call
this.target = {};
this.source = source;
if (this.source.otherProperties != null) {
this.setSectionPreviewId();
this.processImageMap(
this.getTeaserSection<CmsImageMap>(FS_TEASER_IMAGE_MAP_SECTION_TEMPLATE_NAME),
this.getTeaserSection<CmsInputTextFormData>(FS_TEASER_IMAGE_ALT_TEXT_SECTION_TEMPLATE_NAME)
);
this.setTeaserHyperlink(this.getTeaserSection<any>(FS_TEASER_HYPERLINK_SECTION_TEMPLATE_NAME));
}
return this.target;
}
private setSectionPreviewId(): void {
this.target.previewId = this.source.otherProperties.previewId;
}
private getTeaserSection<T extends CmsInputTextFormData | CmsImageMap>(identifier: string): T | undefined {
if (this.source.otherProperties.formData != null) {
const section = this.source.otherProperties.formData[identifier];
if (section != null) {
return section as T;
}
}
}
private processImageMap(imageMap: CmsImageMap, imageAltText?: CmsInputTextFormData): void {
if (imageMap != null) {
const { value } = imageMap;
const { areas, media, resolution } = value;
this.target.overlays = { images: [], texts: [], links: [] };
if (media != null) {
this.setBackgroundImage(media, resolution, imageAltText);
this.addOverlays(areas, media);
}
}
}
private setTeaserHyperlink(data: any): void {
// TODO SAPCC-309 teaser content module: link to a different page (category or pdp)
}
private setBackgroundImage(media: CmsImageMapMedia, resolution: CmsImageMapResolution, imageAltText?: CmsInputTextFormData): void {
const usedResolution = resolution?.uid || DEFAULT_RESOLUTION;
this.target.media = {
url: nullSafe(media?.resolutions?.resolutionsMetaData?.[usedResolution]?.url, null),
resolution: usedResolution,
resolutions: nullSafe(media?.resolutions?.resolutionsMetaData, {}),
altText: nullSafe(imageAltText?.value, ''),
mime: nullSafe(media?.pictureMetaData?.mimeType, ''),
};
}
private createOverlayPositionData(
area: ImageLinkTemplate | TextLinkTemplate | SearchLinkLinkTemplate | CategoryLinkTemplate | ProductLinkTemplate | ContentLinkTemplate,
pictureMetaData: PictureMetaData
): OverlayPosition & OverlayDimension {
const positionAndDimension: OverlayPosition & OverlayDimension = {
width: 0,
height: 0,
widthRatio: `0%`,
heightRatio: `0%`,
left: `0%`,
top: `0%`,
};
if (area.rightBottom && area.leftTop && pictureMetaData) {
const rightBottomX = nullSafe(area.rightBottom.x, 0);
const rightBottomY = nullSafe(area.rightBottom.y, 0);
const leftTopX = nullSafe(area.leftTop.x, 0);
const leftTopY = nullSafe(area.leftTop.y, 0);
const widthInPx = rightBottomX - leftTopX;
const heightInPx = rightBottomY - leftTopY;
const pictureMetaDataWidth = nullSafe(pictureMetaData.width, 0);
const pictureMetaDataHeight = nullSafe(pictureMetaData.height, 0);
positionAndDimension.width = widthInPx;
positionAndDimension.height = heightInPx;
positionAndDimension.widthRatio = `${toPercentageValue(widthInPx, pictureMetaDataWidth)}%`;
positionAndDimension.heightRatio = `${toPercentageValue(heightInPx, pictureMetaDataHeight)}%`;
positionAndDimension.left = `${toPercentageValue(leftTopX, pictureMetaDataWidth)}%`;
positionAndDimension.top = `${toPercentageValue(leftTopY, pictureMetaDataHeight)}%`;
}
return positionAndDimension;
}
private addOverlays(
areas: Array<
ImageLinkTemplate | TextLinkTemplate | SearchLinkLinkTemplate | CategoryLinkTemplate | ProductLinkTemplate | ContentLinkTemplate
> | null,
media: { pictureMetaData: PictureMetaData }
): void {
if (media != null && media.pictureMetaData != null && Array.isArray(areas)) {
areas.filter((item) => item != null).forEach((area) => this.addOverlay(area, media));
}
}
private addOverlay(
area: ImageLinkTemplate | TextLinkTemplate | SearchLinkLinkTemplate | CategoryLinkTemplate | ProductLinkTemplate | ContentLinkTemplate,
media: { pictureMetaData: PictureMetaData }
): void {
const { template } = nullSafe(area.link, {});
const positionAndDimension = this.createOverlayPositionData(area, media.pictureMetaData);
if (template && template.uid) {
const result = this.overlayFactory.createOverlay(template.uid, area, positionAndDimension);
switch (template.uid) {
case 'text':
this.target.overlays.texts.push(result as OverlayText);
break;
case 'image':
this.target.overlays.images.push(result as OverlayImage);
break;
case 'search_link':
case 'category_link':
case 'product_link':
case 'content_link':
this.target.overlays.links.push(result as OverlayLink);
break;
default:
console.warn(
`No overlay implementation was found for the template '${template.uid}'! Please extend the TeaserConverter and add an implementation for this template uid`
);
}
}
}
}