Skip to content

Commit 37d442f

Browse files
committed
Fix PR comments
Feature: CMS-47083
1 parent 0e7c9ff commit 37d442f

File tree

4 files changed

+85
-48
lines changed

4 files changed

+85
-48
lines changed

packages/optimizely-cms-sdk/src/infer.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,12 @@ type InferFromDisplayTemplate<T extends DisplayTemplate> =
206206
T extends { settings: infer S }
207207
? {
208208
[K in keyof S]:
209-
S[K] extends { choices: Record<string, any> }
210-
? keyof S[K]['choices']
209+
S[K] extends { choices: Record<string, any>; editor: infer E }
210+
? E extends 'select'
211+
? keyof S[K]['choices']
212+
: E extends 'checkbox'
213+
? 'true' | 'false'
214+
: never
211215
: never;
212216
}
213217
: {};
Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,54 @@
11
import { describe, it, expect } from 'vitest';
22
import { parseDisplaySettings } from '../displayTemplates.js';
33

4+
45
describe('parseDisplaySettings', () => {
56
it('should parse valid display settings correctly', () => {
7+
const template = {
8+
settings: {
9+
layout: { editor: 'select', choices: { grid: {}, list: {} } },
10+
theme: { editor: 'select', choices: { dark: {}, light: {} } }
11+
}
12+
} as any;
13+
614
const input = [
715
{ key: 'layout', value: 'grid' },
8-
{ key: 'theme', value: 'dark' },
16+
{ key: 'theme', value: 'dark' }
917
];
10-
const result = parseDisplaySettings(input);
18+
19+
const result = parseDisplaySettings(input, template.settings);
1120
expect(result).toEqual({
1221
layout: 'grid',
13-
theme: 'dark',
22+
theme: 'dark'
1423
});
1524
});
1625

17-
it('should handle missing properties gracefully', () => {
18-
const input = [{ key: 'layout', value: 'grid' }];
19-
const result = parseDisplaySettings(input);
26+
it('should handle checkbox correctly', () => {
27+
const template = {
28+
settings: {
29+
showImage: { editor: 'checkbox', choices: {} }
30+
}
31+
} as any;
32+
33+
const input = [{ key: 'showImage', value: 'true' }];
34+
const result = parseDisplaySettings(input, template.settings);
2035
expect(result).toEqual({
21-
layout: 'grid',
36+
showImage: 'true'
2237
});
2338
});
2439

25-
it('should return an empty object for null input', () => {
40+
it('should return undefined for null input', () => {
41+
const template = { settings: {} } as any;
2642
const input = null;
27-
const result = parseDisplaySettings(input ?? undefined);
43+
const result = parseDisplaySettings(input, template.settings);
2844
expect(result).toEqual({});
2945
});
3046

31-
it('should return an empty object for undefined input', () => {
47+
it('should return undefined for undefined input', () => {
48+
const template = { settings: {} } as any;
3249
const input = undefined;
33-
const result = parseDisplaySettings(input);
50+
const result = parseDisplaySettings(input, template.settings);
3451
expect(result).toEqual({});
3552
});
3653
});
54+

packages/optimizely-cms-sdk/src/model/displayTemplates.ts

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -62,30 +62,26 @@ export type DisplayTemplate<T = DisplayTemplateVariant> = T & {
6262
__type: 'displayTemplate';
6363
};
6464

65-
// export function parseDisplaySettings(
66-
// displaySettings?: DisplaySettingsType[] | null
67-
// ): Record<string, string> | undefined {
68-
// if (!displaySettings) {
69-
// return undefined; // Return undefined if displaySettings is not provided
70-
// }
71-
72-
// const result: Record<string, string> = {}; // Initialize an empty object
73-
74-
// // Iterate over the input array
75-
// for (const item of displaySettings) {
76-
// // Assign the value to the key in the result object
77-
// result[item.key] = item.value;
78-
// }
79-
80-
// return result;
81-
// }
82-
83-
export const parseDisplaySettings = <T extends DisplayTemplate>(
84-
settings: DisplaySettingsType[] | null | undefined
85-
): Infer<DisplayTemplate> => {
86-
const result = {} as Infer<T>;
87-
settings?.forEach(s => {
88-
result[s.key as keyof Infer<T>] = s.value as Infer<T>[keyof Infer<T>];
65+
66+
export function parseDisplaySettings(
67+
settings: DisplaySettingsType[] | null | undefined,
68+
templateSettings: Record<string, { editor: string; choices: Record<string, any> }>
69+
): Record<string, string> {
70+
if (!settings || settings.length === 0) return {};
71+
72+
const result: Record<string, string> = {};
73+
74+
settings.forEach(s => {
75+
const settingDef = templateSettings[s.key];
76+
if (!settingDef) return;
77+
78+
if (settingDef.editor === 'select') {
79+
result[s.key] = s.value;
80+
} else if (settingDef.editor === 'checkbox') {
81+
result[s.key] = s.value === 'true' ? 'true' : 'false';
82+
}
8983
});
84+
9085
return result;
91-
};
86+
}
87+

packages/optimizely-cms-sdk/src/react/server.tsx

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ import {
1111
DisplaySettingsType,
1212
ExperienceCompositionNode,
1313
InferredContentReference,
14+
Infer,
1415
} from '../infer.js';
1516
import { isComponentNode } from '../util/baseTypeUtil.js';
16-
import { parseDisplaySettings } from '../model/displayTemplates.js';
17-
import { getDisplayTemplateTag } from '../model/displayTemplateRegistry.js';
17+
import { DisplayTemplate, parseDisplaySettings } from '../model/displayTemplates.js';
18+
import { getDisplayTemplate, getDisplayTemplateTag } from '../model/displayTemplateRegistry.js';
1819
import { isDev } from '../util/environment.js';
1920
import { appendToken } from '../util/preview.js';
2021

@@ -72,7 +73,7 @@ export function initReactComponentRegistry(options: InitOptions) {
7273
}
7374

7475
/** Props for the {@linkcode OptimizelyComponent} component */
75-
type OptimizelyComponentProps = {
76+
type OptimizelyComponentProps<T extends DisplayTemplate = DisplayTemplate> = {
7677
/** Data read from the CMS */
7778
opti: {
7879
/** Content type name */
@@ -89,7 +90,7 @@ type OptimizelyComponentProps = {
8990
__composition?: ExperienceCompositionNode;
9091
};
9192

92-
displaySettings?: Record<string, string>;
93+
displaySettings?: Partial<Infer<T>>;
9394
};
9495

9596
export async function OptimizelyComponent({
@@ -107,6 +108,11 @@ export async function OptimizelyComponent({
107108
});
108109

109110
if (!Component) {
111+
console.log(
112+
`[optimizely-cms-sdk] No component found for content type ${opti.__typename
113+
} ${opti.__tag ? `with tag "${opti.__tag}"` : ''}`
114+
);
115+
110116
return (
111117
<FallbackComponent>
112118
No component found for content type <b>{opti.__typename}</b>
@@ -123,16 +129,16 @@ export async function OptimizelyComponent({
123129
);
124130
}
125131

126-
export type StructureContainerProps = {
132+
export type StructureContainerProps<T extends DisplayTemplate = DisplayTemplate> = {
127133
node: ExperienceStructureNode;
128134
children: React.ReactNode;
129135
index?: number;
130-
displaySettings?: Record<string, string>;
136+
displaySettings?: Partial<Infer<T>>;
131137
};
132-
export type ComponentContainerProps = {
138+
export type ComponentContainerProps<T extends DisplayTemplate = DisplayTemplate> = {
133139
node: ExperienceComponentNode;
134140
children: React.ReactNode;
135-
displaySettings?: Record<string, string>;
141+
displaySettings?: Partial<Infer<T>>;
136142
};
137143
export type StructureContainer = (
138144
props: StructureContainerProps
@@ -150,7 +156,14 @@ export function OptimizelyExperience({
150156
}) {
151157
return nodes.map((node) => {
152158
const tag = getDisplayTemplateTag(node.displayTemplateKey);
153-
const parsedDisplaySettings = parseDisplaySettings(node.displaySettings);
159+
const template = node.displayTemplateKey
160+
? getDisplayTemplate(node.displayTemplateKey)
161+
: null;
162+
163+
const parsedDisplaySettings = template
164+
? parseDisplaySettings(node.displaySettings, template.settings)
165+
: {};
166+
console.error(parsedDisplaySettings);
154167

155168
if (isComponentNode(node)) {
156169
const Wrapper = ComponentWrapper ?? React.Fragment;
@@ -251,7 +264,13 @@ export function OptimizelyGridSection({
251264

252265
return nodes.map((node, i) => {
253266
const tag = getDisplayTemplateTag(node.displayTemplateKey);
254-
const parsedDisplaySettings = parseDisplaySettings(node.displaySettings);
267+
const template = node.displayTemplateKey
268+
? getDisplayTemplate(node.displayTemplateKey)
269+
: null;
270+
271+
const parsedDisplaySettings = template
272+
? parseDisplaySettings(node.displaySettings, template.settings)
273+
: {};
255274

256275
if (isComponentNode(node)) {
257276
return (

0 commit comments

Comments
 (0)