/*! * SAPUI5 * Copyright (c) 2025 SAP SE or an SAP affiliate company. All rights reserved. */ import { SearchResultSetItemAttribute } from "../sinaNexTS/sina/SearchResultSetItemAttribute"; import { SearchResultSetItemAttributeBase } from "../sinaNexTS/sina/SearchResultSetItemAttributeBase"; import { SearchResultSetItemAttributeGroup } from "../sinaNexTS/sina/SearchResultSetItemAttributeGroup"; import { AttributesConfiguration } from "../SearchConfigurationTypes"; import { createSubAttributeMap, isIcon, parseTemplate } from "./util"; import { assembleAttributesWithNavigationTarget, assembleAttributeWithNavigationTarget, } from "./assembleAttributeWithNavigationTarget"; import { AttributeType } from "../sinaNexTS/sina/AttributeType"; import { Assembler, AssemblerConstructor } from "./assembler/Assembler"; import { ControlAssembler } from "./assembler/ControlAssembler"; import Control from "sap/ui/core/Control"; import { TextAssembler } from "./assembler/TextAssembler"; import { NavigationTarget } from "../sinaNexTS/sina/NavigationTarget"; import { AttributeFormatType } from "../sinaNexTS/sina/AttributeFormatType"; export interface AttributeRendererProperties { attributesConfiguration?: AttributesConfiguration; assemblerConstructor: AssemblerConstructor; } export class AttributeRenderer { attributesConfiguration: AttributesConfiguration; assemblerConstructor: AssemblerConstructor; public static createControlRenderer( attributesConfiguration: AttributesConfiguration ): AttributeRenderer { return new AttributeRenderer({ attributesConfiguration, assemblerConstructor: ControlAssembler, }); } public static createTextRenderer(): AttributeRenderer { return new AttributeRenderer({ assemblerConstructor: TextAssembler, }); } constructor(attributeRendererProperties: AttributeRendererProperties) { this.attributesConfiguration = attributeRendererProperties.attributesConfiguration ?? {}; this.assemblerConstructor = attributeRendererProperties.assemblerConstructor; } public render(attribute: SearchResultSetItemAttributeBase): T { const assembler = this.createAssembler(); this.assemble(assembler, attribute); return assembler.getResult(); } public renderAttributes( attributes: Array, navigationTarget?: NavigationTarget ): T { const assembler = this.createAssembler(); if (navigationTarget) { assembleAttributesWithNavigationTarget(assembler, attributes, navigationTarget); } else { for (let i = 0; i < attributes.length; ++i) { const attribute = attributes[i]; this.assemble(assembler, attribute); if (attributes.length > 1 && i < attributes.length - 1) { assembler.addText(" "); // separator } } } return assembler.getResult(); } private createAssembler(): Assembler { return new this.assemblerConstructor(); } private assemble(assembler: Assembler, attribute: SearchResultSetItemAttributeBase) { // handle custom rendering const attributeConfiguration = this.attributesConfiguration[attribute.id]; if (attributeConfiguration) { assembler.addControl(attributeConfiguration.render(attribute)); return; } // special rendering for attributes with navigation target if (attribute.defaultNavigationTarget) { assembleAttributeWithNavigationTarget(assembler, attribute); return; } // switch on attribute type if (attribute instanceof SearchResultSetItemAttribute) { this.assembleSimpleAttribute(assembler, attribute); } else if (attribute instanceof SearchResultSetItemAttributeGroup) { this.assembleGroupAttribute(assembler, attribute); } else { // error } } private assembleSimpleAttribute(assembler: Assembler, attribute: SearchResultSetItemAttribute) { if (attribute.metadata.type === AttributeType.ImageUrl) { assembler.addImage( attribute.value, attribute.metadata.format === AttributeFormatType.Round ? "sapElisaRound" : "" ); } else if (isIcon(attribute)) { assembler.addIcon(attribute.value); } else { assembler.addText(attribute.valueHighlighted); } } private assembleGroupAttribute(assembler: Assembler, attribute: SearchResultSetItemAttributeGroup) { // assemble map with attributes by name of attribute in group const subAttributeMap = createSubAttributeMap(attribute); // parse template const parts = parseTemplate(attribute.template); // process parts of template for (const part of parts) { let subAttribute; switch (part.type) { case "string": assembler.addText(part.value); break; case "placeholder": subAttribute = subAttributeMap[part.value]; if (subAttribute) { this.assemble(assembler, subAttribute); } else { assembler.addText(`{${part.value}}`); // should not happen, for debugging } break; } } } }