Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 2 additions & 55 deletions __test__/test-website/src/app/all/[...slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,3 @@
import {
BlankSection,
Component1,
Component1A,
Component1B,
Component2,
Component2A,
Component3,
Component3C,
ct1,
ct2,
ct3,
dt1,
dt2,
dt3,
} from '@/components/with-display-templates';
import {
initContentTypeRegistry,
initDisplayTemplateRegistry,
} from '@optimizely/cms-sdk';
import { initReactComponentRegistry } from '@optimizely/cms-sdk/react/server';
import RootLayout from '@/app/en/layout';

initContentTypeRegistry([ct1, ct2, ct3]);
initDisplayTemplateRegistry([dt1, dt2, dt3]);
initReactComponentRegistry({
resolver: {
test_c1: {
default: Component1,
tags: {
tagA: Component1A,
tagB: Component1B,
},
},
test_c2: Component2,
'test_c2:tagA': Component2A,
test_c3: {
default: Component3,
tags: {
tagC: Component3C,
},
},
BlankSection: BlankSection,
},
});

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
export default RootLayout;
19 changes: 18 additions & 1 deletion __test__/test-website/src/app/en/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import {
BlankSection,
BlankSection2,
Column,
ColumnA,
Component1,
Component1A,
Component1B,
Expand All @@ -13,6 +16,11 @@ import {
dt1,
dt2,
dt3,
dt4,
dt5,
dt6,
Row,
RowA,
} from '@/components/with-display-templates';
import {
initContentTypeRegistry,
Expand All @@ -21,7 +29,7 @@ import {
import { initReactComponentRegistry } from '@optimizely/cms-sdk/react/server';

initContentTypeRegistry([ct1, ct2, ct3]);
initDisplayTemplateRegistry([dt1, dt2, dt3]);
initDisplayTemplateRegistry([dt1, dt2, dt3, dt4, dt5, dt6]);
initReactComponentRegistry({
resolver: {
test_c1: {
Expand All @@ -40,6 +48,15 @@ initReactComponentRegistry({
},
},
BlankSection: BlankSection,
'BlankSection:tagA': BlankSection2,
_Row: {
default: Row,
tags: {
tagA: RowA,
},
},
_Column: Column,
'_Column:tagA': ColumnA,
},
});

Expand Down
17 changes: 2 additions & 15 deletions __test__/test-website/src/app/preview/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
export const metadata = {
title: 'Next.js',
description: 'Generated by Next.js',
}
import RootLayout from '@/app/en/layout';

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
export default RootLayout;
6 changes: 5 additions & 1 deletion __test__/test-website/src/app/preview/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ export default async function Page({ searchParams }: Props) {
)
.catch((err) => {
console.log(err.errors);
console.log(err.request.query);
console.log(err.request);

if (err.request?.query) {
console.log(err.request.query);
}
throw err;
});

Expand Down
84 changes: 78 additions & 6 deletions __test__/test-website/src/components/with-display-templates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ export const dt3 = displayTemplate({
tag: 'tagC',
});

export const dt4 = displayTemplate({
key: 'test_dt4',
baseType: '_section',
displayName: 'test dt4',
isDefault: false,
settings: {},
tag: 'tagA',
});

export const dt5 = displayTemplate({
key: 'test_dt5',
nodeType: 'row',
displayName: 'test dt5',
isDefault: false,
settings: {},
tag: 'tagA',
});

export const dt6 = displayTemplate({
key: 'test_dt6',
nodeType: 'column',
displayName: 'test dt6',
isDefault: false,
settings: {},
tag: 'tagA',
});

type Props1 = { opti: Infer<typeof ct1> };
type Props2 = { opti: Infer<typeof ct2> };
type Props3 = { opti: Infer<typeof ct3> };
Expand Down Expand Up @@ -106,19 +133,55 @@ export function Component3C({ opti }: Props3) {
);
}

function Row({ children, node }: StructureContainerProps) {
export function Row({ children, node }: StructureContainerProps) {
return (
<>
<h3>This is row (Row) {node.key}</h3>
{children}
</>
);
}

export function Column({ children, node }: StructureContainerProps) {
return (
<>
<h3>This is row {node.key}</h3>
<h4>This is column (Column) {node.key}</h4>
{children}
</>
);
}

function Column({ children, node }: StructureContainerProps) {
export function Row2({ children, node }: StructureContainerProps) {
return (
<>
<h4>This is column {node.key}</h4>
<h3>This is row (Row2) {node.key}</h3>
{children}
</>
);
}

export function Column2({ children, node }: StructureContainerProps) {
return (
<>
<h4>This is column (Column2) {node.key}</h4>
{children}
</>
);
}

export function RowA({ children, node }: StructureContainerProps) {
return (
<>
<h3>This is row (RowA) {node.key}</h3>
{children}
</>
);
}

export function ColumnA({ children, node }: StructureContainerProps) {
return (
<>
<h4>This is column (ColumnA) {node.key}</h4>
{children}
</>
);
Expand All @@ -127,8 +190,17 @@ function Column({ children, node }: StructureContainerProps) {
export function BlankSection({ opti }: BlankSectionProps) {
return (
<>
<h2>This is section {opti.key}</h2>
<OptimizelyGridSection nodes={opti.nodes} row={Row} column={Column} />
<h2>This is BlankSection {opti.key}</h2>
<OptimizelyGridSection nodes={opti.nodes} />
</>
);
}

export function BlankSection2({ opti }: BlankSectionProps) {
return (
<>
<h2>This is BlankSection2 {opti.key}</h2>
<OptimizelyGridSection nodes={opti.nodes} row={Row2} column={Column2} />
</>
);
}
61 changes: 40 additions & 21 deletions packages/optimizely-cms-sdk/src/react/server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ type OptimizelyComponentProps = {
/** Display template tag (if any) */
__tag?: string;

displayTemplateKey?: string | null;

/** Preview context */
__context?: { edit: boolean; preview_token: string };

Expand All @@ -96,10 +98,9 @@ export async function OptimizelyComponent({
if (!componentRegistry) {
throw new Error('You should call `initReactComponentRegistry` first');
}

const dtKey = opti.composition?.displayTemplateKey ?? opti.displayTemplateKey;
const Component = await componentRegistry.getComponent(opti.__typename, {
tag:
opti.__tag ?? getDisplayTemplateTag(opti.composition?.displayTemplateKey),
tag: opti.__tag ?? getDisplayTemplateTag(dtKey),
});

if (!Component) {
Expand Down Expand Up @@ -230,46 +231,60 @@ function FallbackComponent({ children }: { children: ReactNode }) {
}

type OptimizelyGridSectionProps = {
nodes?: ExperienceNode[];
nodes: ExperienceNode[];
row?: StructureContainer;
column?: StructureContainer;
displaySettings?: DisplaySettingsType[];
};

const fallbacks: Record<string, StructureContainer> = {
row: FallbackRow,
column: FallbackColumn,
};

export function OptimizelyGridSection({
nodes,
row = FallbackRow,
column = FallbackColumn,
row,
column,
}: OptimizelyGridSectionProps) {
if (!nodes) {
// TODO: Handle beter
throw new Error('Nodes must be an array');
}
const locallyDefined: Record<string, StructureContainer | undefined> = {
row,
column,
};

return nodes.map((node, i) => {
// get component key(tag) from the display template
const key = getDisplayTemplateTag(node.displayTemplateKey);
// get the parsed display settings (stlyes, classes etc.)
const tag = getDisplayTemplateTag(node.displayTemplateKey);
const parsedDisplaySettings = parseDisplaySettings(node.displaySettings);

if (isComponentNode(node)) {
return (
<OptimizelyComponent
opti={{
...node.component,
__tag: key,
__tag: tag,
}}
key={node.key}
displaySettings={parsedDisplaySettings}
/>
);
}

const { nodes, nodeType } = node;

const mapper: Record<string, StructureContainer> = { row, column };

// TODO: default component
const Component = mapper[nodeType] ?? React.Fragment;
const { nodeType } = node;
const globalNames: Record<string, string> = {
row: '_Row',
column: '_Column',
};

// Pick the component in the following order:
// 1. Explicitly defined in this component
// 2. Globally defined (in the registry)
// 3. Fallback
// 4. React.Fragment
const Component =
locallyDefined[nodeType] ??
componentRegistry.getComponent(globalNames[nodeType], { tag }) ??
fallbacks[nodeType] ??
React.Fragment;

return (
<Component
Expand All @@ -278,7 +293,11 @@ export function OptimizelyGridSection({
key={node.key}
displaySettings={parsedDisplaySettings}
>
<OptimizelyGridSection row={row} column={column} nodes={nodes} />
<OptimizelyGridSection
row={row}
column={column}
nodes={node.nodes ?? []}
/>
</Component>
);
});
Expand Down