From 01fe87f159b76fba155792f4555ad6be22368232 Mon Sep 17 00:00:00 2001 From: Tristan BOULIERE Date: Thu, 21 Jul 2022 08:38:37 +0000 Subject: [PATCH 1/7] feat: interprets the relative URLs of pagelet parameters "bc_pmc:types.pagelet2-ImageFileRef" generically Until now only parameter that starts with image or video were interpreted Now any parameter that extends "bc_pmc:types.pagelet2-ImageFileRef" will be interpreted --- ...ntent-configuration-parameter.interface.ts | 1 + ...ent-configuration-parameter.mapper.spec.ts | 70 +++++++++++++------ .../content-configuration-parameter.mapper.ts | 49 +++++++------ .../content-pagelet.mapper.spec.ts | 1 + 4 files changed, 77 insertions(+), 44 deletions(-) diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts index 77259f4fe9..94d60d4a5f 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts @@ -1,4 +1,5 @@ export interface ContentConfigurationParameterData { definitionQualifiedName: string; value: string | object; + type?: string; } diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts index ba71332756..a40b075fe8 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts @@ -60,26 +60,54 @@ describe('Content Configuration Parameter Mapper', () => { `); }); - describe('postProcessFileReferences', () => { - it.each([ - ['assets/pwa/pwa_home_teaser_1.jpg', 'assets/pwa/pwa_home_teaser_1.jpg', 'Image'], - [ - 'site:/pwa/pwa_home_teaser_1.jpg', - 'http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg', - 'Image', - ], - [ - 'site:/pwa/pwa_home_teaser_1.jpg', - 'http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg', - 'ImageXS', - ], - ['site:/pwa/pwa_home_teaser_1.jpg', 'site:/pwa/pwa_home_teaser_1.jpg', 'Other'], - ['site:/video/video.mp4', 'http://www.example.org/static/channel/-/site/de_DE/video/video.mp4', 'Video'], - ['https://www.youtube.com/watch?v=ABCDEFG', 'https://www.youtube.com/watch?v=ABCDEFG', 'Video'], - ])(`should transform %s to %s for key %s`, (input, expected, key) => { - expect(contentConfigurationParameterMapper.postProcessFileReferences({ [key]: input })).toEqual({ - [key]: expected, - }); - }); + it('should handle ImageFileReferences', () => { + const input: { [name: string]: ContentConfigurationParameterData } = { + key1: { + definitionQualifiedName: 'name1', + value: 'assets/pwa/pwa_home_teaser_1.jpg', + type: 'bc_pmc:types.pagelet2-ImageFileRef', + }, + key2: { + definitionQualifiedName: 'name2', + value: 'site:/pwa/pwa_home_teaser_1.jpg', + type: 'bc_pmc:types.pagelet2-ImageFileRef', + }, + key3: { + definitionQualifiedName: 'name3', + value: 'http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg', + type: 'bc_pmc:types.pagelet2-ImageFileRef', + }, + key4: { + definitionQualifiedName: 'name4', + value: 'https://www.youtube.com/watch?v=ABCDEFG', + type: 'bc_pmc:types.pagelet2-ImageFileRef', + }, + key5: { + definitionQualifiedName: 'name5', + value: [ + 'assets/pwa/pwa_home_teaser_1.jpg', + 'site:/pwa/pwa_home_teaser_1.jpg', + 'http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg', + 'https://www.youtube.com/watch?v=ABCDEFG', + ], + type: 'bc_pmc:types.pagelet2-ImageFileRef', + }, + }; + + const result = contentConfigurationParameterMapper.fromData(input); + expect(result).toMatchInlineSnapshot(` + Object { + "key1": "assets/pwa/pwa_home_teaser_1.jpg", + "key2": "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "key3": "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "key4": "https://www.youtube.com/watch?v=ABCDEFG", + "key5": Array [ + "assets/pwa/pwa_home_teaser_1.jpg", + "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "https://www.youtube.com/watch?v=ABCDEFG", + ], + } + `); }); }); diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts index bf35111977..0c2f250065 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts @@ -24,34 +24,37 @@ export class ContentConfigurationParameterMapper { if (data) { configurationParameters = Object.entries(data) - .map(([key, value]) => ({ [key]: value.value })) + .map(([key, value]) => ({ [key]: this.postProcessConfigurationParameterValue(value) })) .reduce((acc, val) => ({ ...acc, ...val })); } - this.postProcessFileReferences(configurationParameters); - return configurationParameters; } - /** - * TODO: make this dependant on the type of the configuration parameter once the CMS REST API provides this information - * for now filter all configuration parameters that start with 'Image' or 'Video' - * and where the value does not start with 'http' but contains ':/' - + if the filter matches convert the CMS REST API value in a full server URL to the configured file - */ - postProcessFileReferences(data: ContentConfigurationParameters): ContentConfigurationParameters { - Object.keys(data) - .filter( - key => - (key.startsWith('Image') || key.startsWith('Video')) && - data[key] && - !data[key].toString().startsWith('http') && - data[key].toString().includes(':/') - ) - .forEach(key => { - const split = data[key].toString().split(':'); - data[key] = encodeURI(`${this.staticURL}/${split[0]}/${this.lang}${split[1]}`); - }); - return data; + resolveStaticURL(value: string): string { + if (value.startsWith('http')) { + return value; + } + + if (!value.includes(':/')) { + return value; + } + + const split = value.split(':'); + + return encodeURI(`${this.staticURL}/${split[0]}/${this.lang}${split[1]}`); + } + + postProcessConfigurationParameterValue(data: ContentConfigurationParameterData): string | object | number { + switch (data.type) { + case 'bc_pmc:types.pagelet2-ImageFileRef': + if (Array.isArray(data.value)) { + return data.value.map(x => this.resolveStaticURL(x)); + } else { + return this.resolveStaticURL(data.value.toString()); + } + default: + return data.value; + } } } diff --git a/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts b/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts index ad2f84ddcc..76bebfdeb4 100644 --- a/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts +++ b/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts @@ -166,6 +166,7 @@ describe('Content Pagelet Mapper', () => { Image: { value: 'inSPIRED-inTRONICS-b2c-responsive:/brands/adata.jpg', definitionQualifiedName: 'app_sf_base_cm:component.common.image.pagelet2-Component-Image', + type: 'bc_pmc:types.pagelet2-ImageFileRef', }, }, } as ContentPageletData; From 26e367cee99b893ae5a01720a64da259ab01629f Mon Sep 17 00:00:00 2001 From: Tristan BOULIERE Date: Thu, 21 Jul 2022 09:54:35 +0000 Subject: [PATCH 2/7] type property does not need to be nullable. ICM server guarantees the presence of that property --- .../content-configuration-parameter.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts index 94d60d4a5f..2b45a7bc98 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.interface.ts @@ -1,5 +1,5 @@ export interface ContentConfigurationParameterData { definitionQualifiedName: string; value: string | object; - type?: string; + type: string; } From 6d44e3c98d7ea88e48ca0e879163364faf55849e Mon Sep 17 00:00:00 2001 From: Tristan BOULIERE Date: Thu, 21 Jul 2022 10:12:23 +0000 Subject: [PATCH 3/7] Handle FileRef the same way as ImageFileRef --- ...ent-configuration-parameter.mapper.spec.ts | 53 ++++++++++++++++++- .../content-configuration-parameter.mapper.ts | 1 + 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts index a40b075fe8..2c40efcdd6 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts @@ -60,7 +60,7 @@ describe('Content Configuration Parameter Mapper', () => { `); }); - it('should handle ImageFileReferences', () => { + it('should handle bc_pmc:types.pagelet2-ImageFileRef', () => { const input: { [name: string]: ContentConfigurationParameterData } = { key1: { definitionQualifiedName: 'name1', @@ -110,4 +110,55 @@ describe('Content Configuration Parameter Mapper', () => { } `); }); + + it('should handle bc_pmc:types.pagelet2-FileRef', () => { + const input: { [name: string]: ContentConfigurationParameterData } = { + key1: { + definitionQualifiedName: 'name1', + value: 'assets/pwa/pwa_home_teaser_1.jpg', + type: 'bc_pmc:types.pagelet2-FileRef', + }, + key2: { + definitionQualifiedName: 'name2', + value: 'site:/pwa/pwa_home_teaser_1.jpg', + type: 'bc_pmc:types.pagelet2-FileRef', + }, + key3: { + definitionQualifiedName: 'name3', + value: 'http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg', + type: 'bc_pmc:types.pagelet2-FileRef', + }, + key4: { + definitionQualifiedName: 'name4', + value: 'https://www.youtube.com/watch?v=ABCDEFG', + type: 'bc_pmc:types.pagelet2-FileRef', + }, + key5: { + definitionQualifiedName: 'name5', + value: [ + 'assets/pwa/pwa_home_teaser_1.jpg', + 'site:/pwa/pwa_home_teaser_1.jpg', + 'http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg', + 'https://www.youtube.com/watch?v=ABCDEFG', + ], + type: 'bc_pmc:types.pagelet2-FileRef', + }, + }; + + const result = contentConfigurationParameterMapper.fromData(input); + expect(result).toMatchInlineSnapshot(` + Object { + "key1": "assets/pwa/pwa_home_teaser_1.jpg", + "key2": "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "key3": "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "key4": "https://www.youtube.com/watch?v=ABCDEFG", + "key5": Array [ + "assets/pwa/pwa_home_teaser_1.jpg", + "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "http://www.example.org/static/channel/-/site/de_DE/pwa/pwa_home_teaser_1.jpg", + "https://www.youtube.com/watch?v=ABCDEFG", + ], + } + `); + }); }); diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts index 0c2f250065..6373a5ed62 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts @@ -48,6 +48,7 @@ export class ContentConfigurationParameterMapper { postProcessConfigurationParameterValue(data: ContentConfigurationParameterData): string | object | number { switch (data.type) { case 'bc_pmc:types.pagelet2-ImageFileRef': + case 'bc_pmc:types.pagelet2-FileRef': if (Array.isArray(data.value)) { return data.value.map(x => this.resolveStaticURL(x)); } else { From 775fa20d56f94f03fcf46a85d908c4e7592c182f Mon Sep 17 00:00:00 2001 From: Stefan Hauke Date: Mon, 1 Aug 2022 14:46:58 +0200 Subject: [PATCH 4/7] namin fix test commit --- .../content-configuration-parameter.mapper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts index 6373a5ed62..5185d2a559 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts @@ -24,7 +24,7 @@ export class ContentConfigurationParameterMapper { if (data) { configurationParameters = Object.entries(data) - .map(([key, value]) => ({ [key]: this.postProcessConfigurationParameterValue(value) })) + .map(([key, value]) => ({ [key]: this.postProcessData(value) })) .reduce((acc, val) => ({ ...acc, ...val })); } @@ -45,7 +45,7 @@ export class ContentConfigurationParameterMapper { return encodeURI(`${this.staticURL}/${split[0]}/${this.lang}${split[1]}`); } - postProcessConfigurationParameterValue(data: ContentConfigurationParameterData): string | object | number { + postProcessData(data: ContentConfigurationParameterData): string | object | number { switch (data.type) { case 'bc_pmc:types.pagelet2-ImageFileRef': case 'bc_pmc:types.pagelet2-FileRef': From a4c45d255a23e3a3bd8fb823fb55397bd5fb6838 Mon Sep 17 00:00:00 2001 From: Johannes Metzner Date: Mon, 1 Aug 2022 15:54:59 +0200 Subject: [PATCH 5/7] Introduce test-bed values for mandatory prop --- .../content-configuration-parameter.mapper.spec.ts | 3 +++ .../content-pagelet-entry-point.mapper.spec.ts | 2 ++ .../models/content-pagelet/content-pagelet.mapper.spec.ts | 7 +++++++ 3 files changed, 12 insertions(+) diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts index 2c40efcdd6..a38c80b164 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.spec.ts @@ -35,14 +35,17 @@ describe('Content Configuration Parameter Mapper', () => { key1: { definitionQualifiedName: 'name1', value: '1', + type: 'set-id:types.pagelet2-name', }, key2: { definitionQualifiedName: 'name2', value: 'hello', + type: 'set-id:types.pagelet2-name', }, key3: { definitionQualifiedName: 'name3', value: ['hello', 'world'], + type: 'set-id:types.pagelet2-name', }, }; diff --git a/src/app/core/models/content-pagelet-entry-point/content-pagelet-entry-point.mapper.spec.ts b/src/app/core/models/content-pagelet-entry-point/content-pagelet-entry-point.mapper.spec.ts index 224b664a11..68ce57cbd2 100644 --- a/src/app/core/models/content-pagelet-entry-point/content-pagelet-entry-point.mapper.spec.ts +++ b/src/app/core/models/content-pagelet-entry-point/content-pagelet-entry-point.mapper.spec.ts @@ -40,6 +40,7 @@ describe('Content Pagelet Entry Point Mapper', () => { key1: { definitionQualifiedName: 'fq', value: 'hallo 1', + type: 'set-id:types.pagelet2-name', }, }, slots: { @@ -56,6 +57,7 @@ describe('Content Pagelet Entry Point Mapper', () => { key11: { definitionQualifiedName: 'fq', value: 'test', + type: 'set-id:types.pagelet2-name', }, }, }, diff --git a/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts b/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts index 76bebfdeb4..636488d601 100644 --- a/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts +++ b/src/app/core/models/content-pagelet/content-pagelet.mapper.spec.ts @@ -35,6 +35,7 @@ describe('Content Pagelet Mapper', () => { key: { definitionQualifiedName: 'quali', value: 'test', + type: 'set-id:types.pagelet2-name', }, }, }; @@ -53,6 +54,7 @@ describe('Content Pagelet Mapper', () => { key: { definitionQualifiedName: 'quali', value: 'test', + type: 'set-id:types.pagelet2-name', }, }, slots: { @@ -78,6 +80,7 @@ describe('Content Pagelet Mapper', () => { key: { definitionQualifiedName: 'quali', value: 'test', + type: 'set-id:types.pagelet2-name', }, }, slots: { @@ -106,6 +109,7 @@ describe('Content Pagelet Mapper', () => { key1: { definitionQualifiedName: 'fq', value: 'test-key1', + type: 'set-id:types.pagelet2-name', }, }, slots: { @@ -122,6 +126,7 @@ describe('Content Pagelet Mapper', () => { key3: { definitionQualifiedName: 'fq', value: '1', + type: 'set-id:types.pagelet2-name', }, }, }, @@ -134,10 +139,12 @@ describe('Content Pagelet Mapper', () => { key1: { definitionQualifiedName: 'name1', value: 'hallo', + type: 'set-id:types.pagelet2-name', }, key2: { definitionQualifiedName: 'name2', value: ['hallo', 'welt'], + type: 'set-id:types.pagelet2-name', }, }, }, From f435c55be5f250b8400386e661e66f4b76c39db9 Mon Sep 17 00:00:00 2001 From: Johannes Metzner Date: Mon, 1 Aug 2022 15:59:07 +0200 Subject: [PATCH 6/7] Add visibility modifier to method declaration --- .../content-configuration-parameter.mapper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts index 5185d2a559..27281b814b 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts @@ -31,7 +31,7 @@ export class ContentConfigurationParameterMapper { return configurationParameters; } - resolveStaticURL(value: string): string { + private resolveStaticURL(value: string): string { if (value.startsWith('http')) { return value; } @@ -45,7 +45,7 @@ export class ContentConfigurationParameterMapper { return encodeURI(`${this.staticURL}/${split[0]}/${this.lang}${split[1]}`); } - postProcessData(data: ContentConfigurationParameterData): string | object | number { + private postProcessData(data: ContentConfigurationParameterData): string | object | number { switch (data.type) { case 'bc_pmc:types.pagelet2-ImageFileRef': case 'bc_pmc:types.pagelet2-FileRef': From 2cc3aec6c508684da0dc50e95242761d81a8caf8 Mon Sep 17 00:00:00 2001 From: Johannes Metzner Date: Mon, 1 Aug 2022 16:27:34 +0200 Subject: [PATCH 7/7] Mention a todo for a better way to inject handlers --- .../content-configuration-parameter.mapper.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts index 27281b814b..7c23aeb651 100644 --- a/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts +++ b/src/app/core/models/content-configuration-parameter/content-configuration-parameter.mapper.ts @@ -45,6 +45,10 @@ export class ContentConfigurationParameterMapper { return encodeURI(`${this.staticURL}/${split[0]}/${this.lang}${split[1]}`); } + /** + * TODO: Make this method use name-based plugin mechanism to delegate post processing of + * configuration parameter data to specific handler. + */ private postProcessData(data: ContentConfigurationParameterData): string | object | number { switch (data.type) { case 'bc_pmc:types.pagelet2-ImageFileRef':