From 3a9575e64d49e5568e44b1b2e1323e295452e13d Mon Sep 17 00:00:00 2001 From: Florent Letendre Date: Thu, 24 Oct 2024 15:16:20 -0400 Subject: [PATCH] first commit --- .env-cmdrc | 2 +- .../services/opf-resource-loader.service.ts | 57 ++++++++++++++++--- .../opf-cta-element.component.html | 1 + .../opf-cta-element.component.ts | 10 +++- .../opf-cta-scripts.service.ts | 15 ++++- .../features/opf/opf-feature.module.ts | 4 +- 6 files changed, 72 insertions(+), 17 deletions(-) diff --git a/.env-cmdrc b/.env-cmdrc index 1406945f681..aeb0f17cde2 100644 --- a/.env-cmdrc +++ b/.env-cmdrc @@ -34,7 +34,7 @@ }, "opf": { "CX_OPF": "true", - "CX_BASE_URL": "https://api.cp96avkh5f-integrati2-d2-public.model-t.cc.commerce.ondemand.com" + "CX_BASE_URL": "https://api.cp96avkh5f-integrati2-s1-public.model-t.cc.commerce.ondemand.com" }, "cpq": { "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s1-public.model-t.myhybris.cloud/", diff --git a/integration-libs/opf/base/root/services/opf-resource-loader.service.ts b/integration-libs/opf/base/root/services/opf-resource-loader.service.ts index 1b8d2de5915..971f9f200c7 100644 --- a/integration-libs/opf/base/root/services/opf-resource-loader.service.ts +++ b/integration-libs/opf/base/root/services/opf-resource-loader.service.ts @@ -5,8 +5,14 @@ */ import { DOCUMENT, isPlatformServer } from '@angular/common'; -import { Inject, Injectable, PLATFORM_ID } from '@angular/core'; -import { ScriptLoader } from '@spartacus/core'; +import { + ElementRef, + inject, + Inject, + Injectable, + PLATFORM_ID, +} from '@angular/core'; +import { ScriptLoader, WindowRef } from '@spartacus/core'; import { OpfDynamicScriptResource, @@ -24,6 +30,8 @@ export class OpfResourceLoaderService extends ScriptLoader { super(document, platformId); } + protected winRef = inject(WindowRef); + protected readonly OPF_RESOURCE_ATTRIBUTE_KEY = 'data-opf-resource'; protected loadedResources: OpfDynamicScriptResource[] = []; @@ -137,15 +145,46 @@ export class OpfResourceLoaderService extends ScriptLoader { } } - executeScriptFromHtml(html: string | undefined) { - if (html) { - const element = new DOMParser().parseFromString(html, 'text/html'); - const script = element.getElementsByTagName('script'); - if (!script?.[0]?.innerText) { - return; + executeScriptFromHtml( + htmlString: string | undefined, + htmlElement?: HTMLElement | ElementRef + ) { + //////// + let el: HTMLElement; + if (!htmlString) { + return; + } + + if (htmlElement) { + if (htmlElement instanceof ElementRef) { + el = htmlElement.nativeElement; + } else { + el = htmlElement; } - Function(script[0].innerText)(); + + const windowDocument = this.winRef.document; + if (windowDocument) { + el.innerHTML = htmlString; + + Array.from(el.getElementsByTagName('script')).forEach((script) => { + const parentNode = script.parentNode; + const newScriptTag = windowDocument.createElement('script'); + newScriptTag.type = 'text/javascript'; + newScriptTag.text = script.text; + parentNode?.removeChild(script); + parentNode?.appendChild(newScriptTag); + }); + } + return; + } + /////// + + const element = new DOMParser().parseFromString(htmlString, 'text/html'); + const script = element.getElementsByTagName('script'); + if (!script?.[0]?.innerText) { + return; } + Function(script[0].innerText)(); } clearAllProviderResources() { diff --git a/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.html b/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.html index 7ce3521556a..5fe59588967 100644 --- a/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.html +++ b/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.html @@ -1,4 +1,5 @@
diff --git a/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.ts b/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.ts index 55a986d62cb..5a6e973dd09 100644 --- a/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.ts +++ b/integration-libs/opf/cta/components/opf-cta-element/opf-cta-element.component.ts @@ -8,7 +8,9 @@ import { AfterViewInit, ChangeDetectionStrategy, Component, + ElementRef, Input, + ViewChild, inject, } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @@ -22,6 +24,7 @@ import { OpfCtaScriptsService } from '../opf-cta-scripts/opf-cta-scripts.service changeDetection: ChangeDetectionStrategy.OnPush, }) export class OpfCtaElementComponent implements AfterViewInit { + @ViewChild('ctaElementContainer') container: ElementRef; protected sanitizer = inject(DomSanitizer); protected opfCtaScriptsService = inject(OpfCtaScriptsService); protected windowRef = inject(WindowRef); @@ -30,11 +33,14 @@ export class OpfCtaElementComponent implements AfterViewInit { ngAfterViewInit(): void { this.windowRef.isBrowser() && - this.opfCtaScriptsService.loadAndRunScript(this.ctaScriptHtml); + this.opfCtaScriptsService.loadAndRunScript( + this.ctaScriptHtml, + this.container + ); } renderHtml(html: string): SafeHtml { return this.windowRef.isBrowser() - ? this.sanitizer.bypassSecurityTrustHtml(this.removeScriptTags(html)) + ? this.sanitizer.bypassSecurityTrustHtml(html) : html; } diff --git a/integration-libs/opf/cta/components/opf-cta-scripts/opf-cta-scripts.service.ts b/integration-libs/opf/cta/components/opf-cta-scripts/opf-cta-scripts.service.ts index 8eaa6846914..347c022d5fb 100644 --- a/integration-libs/opf/cta/components/opf-cta-scripts/opf-cta-scripts.service.ts +++ b/integration-libs/opf/cta/components/opf-cta-scripts/opf-cta-scripts.service.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Injectable, inject } from '@angular/core'; +import { ElementRef, Injectable, inject } from '@angular/core'; import { CmsService } from '@spartacus/core'; import { Observable, Subscription, of, throwError } from 'rxjs'; import { concatMap, filter, finalize, map, take, tap } from 'rxjs/operators'; @@ -40,7 +40,8 @@ export class OpfCtaScriptsService { protected subList: Array = []; loadAndRunScript( - script: OpfDynamicScript + script: OpfDynamicScript, + elRef: ElementRef ): Promise { const html = script?.html; @@ -50,7 +51,7 @@ export class OpfCtaScriptsService { .loadProviderResources(script.jsUrls, script.cssUrls) .then(() => { if (html) { - this.opfResourceLoaderService.executeScriptFromHtml(html); + this.opfResourceLoaderService.executeScriptFromHtml(html, elRef); resolve(script); } else { resolve(undefined); @@ -183,4 +184,12 @@ export class OpfCtaScriptsService { map((state) => state.data?.map((val) => val.id) as number[]) ); } + + protected removeScriptTags(html: string) { + const element = new DOMParser().parseFromString(html, 'text/html'); + Array.from(element.getElementsByTagName('script')).forEach((script) => { + html = html.replace(script.outerHTML, ''); + }); + return html; + } } diff --git a/projects/storefrontapp/src/app/spartacus/features/opf/opf-feature.module.ts b/projects/storefrontapp/src/app/spartacus/features/opf/opf-feature.module.ts index 13ed200b19e..199f507a083 100644 --- a/projects/storefrontapp/src/app/spartacus/features/opf/opf-feature.module.ts +++ b/projects/storefrontapp/src/app/spartacus/features/opf/opf-feature.module.ts @@ -118,8 +118,8 @@ if (environment.b2b) { provideConfig({ opf: { opfBaseUrl: - 'https://cp96avkh5f-integrati2-d2.opf.commerce.stage.context.cloud.sap/commerce-cloud-adapter-stage/storefront', - commerceCloudPublicKey: 'k2N3m3TJPLragwia5ZUvS/qkIPVQoy5qjUkOAB6Db+U=', + 'https://opf-iss-d0.opf.commerce.stage.context.cloud.sap/commerce-cloud-adapter/storefront', + commerceCloudPublicKey: 'ab4RhYGZ+w5B0SALMPOPlepWk/kmDQjTy2FU5hrQoFg=', }, }), ...extensionProviders,