@merkle-open/magnolia-headless-frontend-nextjs 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merkle-open/magnolia-headless-frontend-nextjs",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Magnolia headless frontend nextJs",
5
5
  "license": "MIT",
6
6
  "author": "Merkle Inc.",
@@ -10,6 +10,7 @@ import type { FrontendApiEndpointsProvider, HeadlessConfigProviderI } from '../c
10
10
  import { type StylesheetProviderI } from '../config/StylesheetProvider.ts';
11
11
  import { type ComponentMappingsProviderI } from '../config/ComponentMappingsProvider.ts';
12
12
  import { ThemeValidator } from '../helper/ThemeValidator.ts';
13
+ import { EditablePage } from '../templates/pages/__magnolia-editable-page/EditablePage.tsx';
13
14
 
14
15
  export abstract class AbstractDynamicErrorPage extends AbstractDynamicPage {
15
16
  private readonly frontendApisProvider: FrontendApiEndpointsProvider;
@@ -19,11 +20,12 @@ export abstract class AbstractDynamicErrorPage extends AbstractDynamicPage {
19
20
  configProvider: HeadlessConfigProviderI,
20
21
  StylesheetProviderI: StylesheetProviderI,
21
22
  themeValidator: ThemeValidator,
23
+ editablePage: EditablePage,
22
24
  private readonly restClient: RestClient,
23
25
  private readonly staticErrorPage: StaticErrorPage,
24
26
  protected readonly magnoliaContextProvider: MagnoliaContextProvider,
25
27
  ) {
26
- super(componentMappingsProvider, StylesheetProviderI, themeValidator);
28
+ super(componentMappingsProvider, StylesheetProviderI, themeValidator, editablePage);
27
29
  this.frontendApisProvider = configProvider.get().frontendApisProvider;
28
30
  }
29
31
 
@@ -1,5 +1,5 @@
1
1
  import { ExtendedMagnoliaContext } from '../helper/MagnoliaContextProvider.ts';
2
- import { Content } from '../helper/MagnoliaPageRestClient.ts';
2
+ import PageProps from '../templates/pages/BaseProps.ts';
3
3
  import { MgnlTemplateAnnotations } from '@magnolia/frontend-helpers-base';
4
4
  import React, { ReactNode } from 'react';
5
5
  import { MagnoliaConfig, RefService } from '@magnolia/react-editor';
@@ -13,9 +13,10 @@ export abstract class AbstractDynamicPage {
13
13
  private readonly componentMappingsProvider: ComponentMappingsProviderI,
14
14
  private readonly StylesheetProviderI: StylesheetProviderI,
15
15
  private readonly themeValidator: ThemeValidator,
16
+ private readonly editablePage: EditablePage,
16
17
  ) {}
17
18
 
18
- protected renderBase(magnoliaContext: ExtendedMagnoliaContext, content: Content, templateAnnotations: MgnlTemplateAnnotations): ReactNode {
19
+ protected renderBase(magnoliaContext: ExtendedMagnoliaContext, content: PageProps, templateAnnotations: MgnlTemplateAnnotations): ReactNode {
19
20
  const config: MagnoliaConfig = {
20
21
  componentMappings: this.componentMappingsProvider.getComponentMappings(),
21
22
  };
@@ -29,12 +30,12 @@ export abstract class AbstractDynamicPage {
29
30
  {this.getStylesheet(magnoliaContext, content).map((stylesheet) => (
30
31
  <link rel="stylesheet" href={stylesheet} precedence="high" />
31
32
  ))}
32
- <EditablePage content={content} config={config} templateAnnotations={templateAnnotations} magnoliaContext={magnoliaContext} />
33
+ {this.editablePage.render({ content, config, templateAnnotations, magnoliaContext })}
33
34
  </div>
34
35
  );
35
36
  }
36
37
 
37
- private getStylesheet(magnoliaContext: ExtendedMagnoliaContext, content: Content): string[] {
38
+ private getStylesheet(magnoliaContext: ExtendedMagnoliaContext, content: PageProps): string[] {
38
39
  return this.StylesheetProviderI.get(magnoliaContext, this.themeValidator.getValidatedTheme(content.theme));
39
40
  }
40
41
  }
@@ -13,6 +13,7 @@ import { type ComponentMappingsProviderI } from '../config/ComponentMappingsProv
13
13
  import { StaticErrorPage } from '../templates/pages/_error-static/ErrorStatic.tsx';
14
14
  import { CombinedComponentMappingsProvider } from '../templates/ComponentMappingsProvider.ts';
15
15
  import { ThemeValidator } from '../helper/ThemeValidator.ts';
16
+ import { EditablePage } from '../templates/pages/__magnolia-editable-page/EditablePage.tsx';
16
17
 
17
18
  @injectable()
18
19
  export class DynamicErrorPage extends AbstractDynamicErrorPage {
@@ -21,11 +22,12 @@ export class DynamicErrorPage extends AbstractDynamicErrorPage {
21
22
  @inject(HEADLESS_CONFIG_PROVIDER_TOKEN) configProvider: HeadlessConfigProviderI,
22
23
  @inject(STYLESHEET_PROVIDER_TOKEN) StylesheetProviderI: StylesheetProviderI,
23
24
  @inject(ThemeValidator) themeValidator: ThemeValidator,
25
+ @inject(EditablePage) editablePage: EditablePage,
24
26
  @inject(RestClient) restClient: RestClient,
25
27
  @inject(StaticErrorPage) staticErrorPage: StaticErrorPage,
26
28
  @inject(MagnoliaContextProvider) magnoliaContextProvider: MagnoliaContextProvider,
27
29
  ) {
28
- super(componentMappingsProvider, configProvider, StylesheetProviderI, themeValidator, restClient, staticErrorPage, magnoliaContextProvider);
30
+ super(componentMappingsProvider, configProvider, StylesheetProviderI, themeValidator, editablePage, restClient, staticErrorPage, magnoliaContextProvider);
29
31
  }
30
32
 
31
33
  public render(errorType: ErrorType): ReactNode {
@@ -14,6 +14,7 @@ import { type ComponentMappingsProviderI } from '../config/ComponentMappingsProv
14
14
  import { StaticErrorPage } from '../templates/pages/_error-static/ErrorStatic.tsx';
15
15
  import { CombinedComponentMappingsProvider } from '../templates/ComponentMappingsProvider.ts';
16
16
  import { ThemeValidator } from '../helper/ThemeValidator.ts';
17
+ import { EditablePage } from '../templates/pages/__magnolia-editable-page/EditablePage.tsx';
17
18
 
18
19
  @injectable()
19
20
  export class DynamicErrorPageGlobal extends AbstractDynamicErrorPage {
@@ -22,12 +23,13 @@ export class DynamicErrorPageGlobal extends AbstractDynamicErrorPage {
22
23
  @inject(HEADLESS_CONFIG_PROVIDER_TOKEN) configProvider: HeadlessConfigProviderI,
23
24
  @inject(STYLESHEET_PROVIDER_TOKEN) StylesheetProviderI: StylesheetProviderI,
24
25
  @inject(ThemeValidator) themeValidator: ThemeValidator,
26
+ @inject(EditablePage) editablePage: EditablePage,
25
27
  @inject(RestClient) restClient: RestClient,
26
28
  @inject(StaticErrorPage) staticErrorPage: StaticErrorPage,
27
29
  @inject(MagnoliaContextProvider) magnoliaContextProvider: MagnoliaContextProvider,
28
30
  @inject(DynamicPageLayout) private readonly dynamicPageLayout: DynamicPageLayout,
29
31
  ) {
30
- super(componentMappingsProvider, configProvider, StylesheetProviderI, themeValidator, restClient, staticErrorPage, magnoliaContextProvider);
32
+ super(componentMappingsProvider, configProvider, StylesheetProviderI, themeValidator, editablePage, restClient, staticErrorPage, magnoliaContextProvider);
31
33
  }
32
34
 
33
35
  public render(errorType: ErrorType): ReactNode {
@@ -14,6 +14,7 @@ import { type StylesheetProviderI, STYLESHEET_PROVIDER_TOKEN } from '../config/S
14
14
  import { type ComponentMappingsProviderI } from '../config/ComponentMappingsProvider.ts';
15
15
  import { CombinedComponentMappingsProvider } from '../templates/ComponentMappingsProvider.ts';
16
16
  import { ThemeValidator } from '../helper/ThemeValidator.ts';
17
+ import { EditablePage } from '../templates/pages/__magnolia-editable-page/EditablePage.tsx';
17
18
 
18
19
  @injectable()
19
20
  export class DynamicPage extends AbstractDynamicPage {
@@ -21,12 +22,13 @@ export class DynamicPage extends AbstractDynamicPage {
21
22
  @inject(CombinedComponentMappingsProvider) componentMappingsProvider: ComponentMappingsProviderI,
22
23
  @inject(STYLESHEET_PROVIDER_TOKEN) StylesheetProviderI: StylesheetProviderI,
23
24
  @inject(ThemeValidator) themeValidator: ThemeValidator,
25
+ @inject(EditablePage) editablePage: EditablePage,
24
26
  @inject(MagnoliaContextProvider) private readonly magnoliaContextProvider: MagnoliaContextProvider,
25
27
  @inject(MagnoliaPageRestClient) private readonly magnoliaPageRestClient: MagnoliaPageRestClient,
26
28
  @inject(MetadataProvider) private readonly metadataProvider: MetadataProvider,
27
29
  @inject(UrlProvider) private readonly urlProvider: UrlProvider,
28
30
  ) {
29
- super(componentMappingsProvider, StylesheetProviderI, themeValidator);
31
+ super(componentMappingsProvider, StylesheetProviderI, themeValidator, editablePage);
30
32
  }
31
33
 
32
34
  public async render(pageProps: PageProps): Promise<ReactNode> {
@@ -1,16 +1,10 @@
1
- import { IMagnoliaContext, MgnlContent, MgnlTemplateAnnotations } from '@magnolia/frontend-helpers-base';
1
+ import { IMagnoliaContext, MgnlTemplateAnnotations } from '@magnolia/frontend-helpers-base';
2
2
  import { RestClient } from './RestClient.ts';
3
3
  import { MagnoliaContextProvider } from './MagnoliaContextProvider.ts';
4
- import MetaProps from './MetaProps.ts';
4
+ import PageProps from '../templates/pages/BaseProps.ts';
5
5
  import { inject, injectable } from 'tsyringe';
6
6
  import { type HeadlessConfigProviderI, MagnoliaApiEndpointsProvider, HEADLESS_CONFIG_PROVIDER_TOKEN } from '../config/ConfigProvider.ts';
7
7
 
8
- export interface Content extends MgnlContent {
9
- cspHeader?: string;
10
- meta: MetaProps;
11
- theme?: string;
12
- }
13
-
14
8
  export enum ErrorType {
15
9
  PAGE_NOT_FOUND = '404',
16
10
  INTERNAL_SERVER_ERROR = '500',
@@ -28,7 +22,7 @@ export class MagnoliaPageRestClient {
28
22
  this.apisProvider = configProvider.get().magnoliaApisProvider;
29
23
  }
30
24
 
31
- public async getErrorPageContent(url: URL, errorType: ErrorType): Promise<Content> {
25
+ public async getErrorPageContent(url: URL, errorType: ErrorType): Promise<PageProps> {
32
26
  const magnoliaContext = this.magnoliaContextProvider.getMagnoliaContext(url);
33
27
  const queryParams = new URLSearchParams();
34
28
  queryParams.set('errorCode', errorType.toString());
@@ -37,7 +31,7 @@ export class MagnoliaPageRestClient {
37
31
  return this.restClient.fetchMagnoliaBasicAuth(errorPagesApiUrl).then((response) => this.restClient.getJson(errorPagesApiUrl, response));
38
32
  }
39
33
 
40
- public async getPageContent(url: URL): Promise<Content> {
34
+ public async getPageContent(url: URL): Promise<PageProps> {
41
35
  const magnoliaContext = this.magnoliaContextProvider.getMagnoliaContext(url);
42
36
  const queryParams = new URLSearchParams(magnoliaContext.searchParams);
43
37
  queryParams.delete('jwt');
@@ -2,7 +2,7 @@
2
2
  import type { OpenGraph } from 'next/dist/lib/metadata/types/opengraph-types';
3
3
  // @ts-expect-error: Next.js missing exports prevents ESM resolution with 'nodenext'.
4
4
  import type { Twitter } from 'next/dist/lib/metadata/types/twitter-types';
5
- import MetaProps, { OpenGraph as HeadlessOpenGraph } from './MetaProps.ts';
5
+ import { MetaProps, OpenGraph as HeadlessOpenGraph } from '../templates/pages/BaseProps.ts';
6
6
  import { Metadata } from 'next';
7
7
  import { injectable } from 'tsyringe';
8
8
 
@@ -5,5 +5,4 @@ export * from './BrowserLanguageProvider.ts';
5
5
  export * from './Logger.ts';
6
6
  export * from './RestClient.ts';
7
7
  export * from './MetadataProvider.ts';
8
- export * from './MetaProps.ts';
9
8
  export * from './ThemeValidator.ts';
@@ -2,8 +2,10 @@ import { DependencyContainer } from 'tsyringe';
2
2
 
3
3
  import { CombinedComponentMappingsProvider } from './ComponentMappingsProvider.ts';
4
4
  import { StaticErrorPage } from './pages/_error-static/ErrorStatic.tsx';
5
+ import { EditablePage } from './pages/__magnolia-editable-page/EditablePage.tsx';
5
6
 
6
7
  export default function register(container: DependencyContainer) {
7
8
  container.register(CombinedComponentMappingsProvider, { useClass: CombinedComponentMappingsProvider });
8
9
  container.register(StaticErrorPage, { useClass: StaticErrorPage });
10
+ container.register(EditablePage, { useClass: EditablePage });
9
11
  }
@@ -1,7 +1,12 @@
1
1
  export * from './ComponentMappingsProvider.ts';
2
2
  export type { default as PageBaseProps } from './pages/BaseProps.ts';
3
+ export * from './pages/__magnolia-editable-page/EditablePage.tsx';
4
+ export type { default as EditablePageProps } from './pages/__magnolia-editable-page/EditablePageProps.ts';
3
5
  export type { default as AreaBaseProps } from './areas/BaseProps.ts';
4
6
  export * from './areas/__magnolia-editable-area/EditableArea.tsx';
7
+ export type { default as EditableAreaProps } from './areas/__magnolia-editable-area/EditableAreaProps.ts';
5
8
  export type { default as ComponentBaseProps } from './components/BaseProps.ts';
9
+ export * from './components/__magnolia-editable-component/EditableComponent.tsx';
10
+ export type { default as EditableComponentProps } from './components/__magnolia-editable-component/EditableComponentProps.ts';
6
11
  export * from './pages/_error-static/ErrorStatic.tsx';
7
12
  export type { default as StaticErrorPageProps } from './pages/_error-static/ErrorStaticProps.ts';
@@ -1,5 +1,3 @@
1
- type AreaItems = any;
2
- export default interface Props extends AreaItems {
3
- '@name': string;
4
- '@nodes': string[];
5
- }
1
+ import { MgnlContent } from '@magnolia/frontend-helpers-base';
2
+
3
+ export default interface Props extends MgnlContent {}
@@ -1,27 +1,50 @@
1
- import { EditableArea as MagnoliaEditableArea } from '@magnolia/react-editor';
2
- import React, { ReactNode } from 'react';
1
+ import { EditableArea as MagnoliaEditableArea, RefService } from '@magnolia/react-editor';
2
+ import React, { ReactElement, ReactNode } from 'react';
3
3
  import EditableAreaProps from './EditableAreaProps.ts';
4
- import { ContentRendererService, MgnlContent } from '@magnolia/frontend-helpers-base';
4
+ import { ContentRendererService, IMagnoliaContext, MgnlContent } from '@magnolia/frontend-helpers-base';
5
5
  import { EditableComponent } from '../../components/__magnolia-editable-component/EditableComponent.tsx';
6
6
 
7
- export function EditableArea(props: EditableAreaProps): ReactNode {
8
- const { content, additionalContent, additionalComponentContent } = props;
9
- const componentNodeMapping = content['@nodes'].map((nodeName: any) => [nodeName, merge(content[nodeName], additionalComponentContent)]);
10
- const mergedContent = merge(merge(content, new Map(componentNodeMapping)), additionalContent);
7
+ export class EditableAreaClass {
8
+ constructor(private readonly editableComponent: EditableComponent) {}
9
+
10
+ public render(props: EditableAreaProps): ReactNode {
11
+ const { content, additionalContent, additionalComponentContent } = props;
12
+ const mergedContent = this.merge(content, additionalContent);
13
+ const mergedComponentContents: MgnlContent[] = content?.['@nodes']?.map((nodeName: string): MgnlContent => this.merge(content[nodeName], additionalComponentContent)) || [];
14
+ const children: ReactElement[] = mergedComponentContents?.map((content: MgnlContent, index: number): ReactElement => this.renderComponent(content, index) as ReactElement);
15
+
16
+ return (
17
+ this.shouldRender(children.length > 0, props.renderEmpty) && (
18
+ <MagnoliaEditableArea {...props} content={mergedContent}>
19
+ {children}
20
+ </MagnoliaEditableArea>
21
+ )
22
+ );
23
+ }
11
24
 
12
- const componentContents: MgnlContent[] = content?.['@nodes']?.map((nodeName: string) => content[nodeName] as MgnlContent) || [];
13
- const children = componentContents?.map((item, index) => <EditableComponent key={ContentRendererService.buildKey(item)} content={item} index={index} />);
25
+ protected renderComponent(content: any, index: number): ReactNode {
26
+ return this.editableComponent.render({ key: ContentRendererService.buildKey(content), content: content, index: index });
27
+ }
14
28
 
15
- return (
16
- <MagnoliaEditableArea {...props} content={mergedContent}>
17
- {children}
18
- </MagnoliaEditableArea>
19
- );
29
+ protected merge(...content: any[]): any {
30
+ return content.reduce((previousValue: any, currentValue: any): any => {
31
+ return {
32
+ ...previousValue,
33
+ ...currentValue,
34
+ };
35
+ });
36
+ }
37
+
38
+ protected shouldRender(hasChildren: boolean, renderEmpty?: boolean): boolean {
39
+ if (renderEmpty) {
40
+ return true;
41
+ }
42
+ const magnoliaContext = RefService.getMagnoliaContextRef<IMagnoliaContext>();
43
+ const isEditMode = magnoliaContext?.isMagnoliaEdit;
44
+ return isEditMode || hasChildren;
45
+ }
20
46
  }
21
47
 
22
- function merge(first: any, second: any): any {
23
- return {
24
- ...first,
25
- ...second,
26
- };
48
+ export function EditableArea(props: EditableAreaProps): ReactNode {
49
+ return new EditableAreaClass(new EditableComponent()).render(props);
27
50
  }
@@ -1,7 +1,8 @@
1
1
  import { ReactComponentLike, ReactNodeLike } from 'prop-types';
2
+ import AreaProps from '../BaseProps.ts';
2
3
 
3
4
  export default interface EditableAreaProps {
4
- content: any;
5
+ content: AreaProps;
5
6
  parentTemplateId?: string;
6
7
  className?: any;
7
8
  elementType?: any;
@@ -9,4 +10,5 @@ export default interface EditableAreaProps {
9
10
  children?: ReactNodeLike;
10
11
  additionalContent?: any;
11
12
  additionalComponentContent?: any;
13
+ renderEmpty?: boolean;
12
14
  }
@@ -1,3 +1,3 @@
1
- export default interface Props {
2
- 'mgnl:template': string;
3
- }
1
+ import { MgnlContent } from '@magnolia/frontend-helpers-base';
2
+
3
+ export default interface Props extends MgnlContent {}
@@ -1,23 +1,28 @@
1
1
  import { EditableComponent as MagnoliaEditableComponent, RefService } from '@magnolia/react-editor';
2
2
  import React, { ReactNode } from 'react';
3
3
  import EditableComponentProps from './EditableComponentProps.ts';
4
- import { IMagnoliaContext } from '@magnolia/frontend-helpers-base';
4
+ import { IMagnoliaContext, MgnlContent } from '@magnolia/frontend-helpers-base';
5
5
  import ErrorBoundary from '../../elements/_error/ErrorBoundary.tsx';
6
6
 
7
- export function EditableComponent(props: EditableComponentProps): ReactNode {
8
- const { content, additionalContent } = props;
9
- const magnoliaContext = RefService.getMagnoliaContextRef<IMagnoliaContext>();
7
+ export class EditableComponent {
8
+ public render(props: EditableComponentProps): ReactNode {
9
+ const { content, additionalContent } = props;
10
+ const magnoliaContext: IMagnoliaContext = RefService.getMagnoliaContextRef<IMagnoliaContext>();
11
+ const mergedContent: MgnlContent = this.merge(content, additionalContent);
10
12
 
11
- return (
12
- <ErrorBoundary isEditMode={magnoliaContext.isMagnoliaEdit} throwNotEditMode={false} path={content!['@path']}>
13
- <MagnoliaEditableComponent {...props} content={merge(content, additionalContent)} />
14
- </ErrorBoundary>
15
- );
16
- }
13
+ return (
14
+ <ErrorBoundary isEditMode={magnoliaContext.isMagnoliaEdit} throwNotEditMode={false} path={content!['@path']}>
15
+ <MagnoliaEditableComponent {...props} content={mergedContent} />
16
+ </ErrorBoundary>
17
+ );
18
+ }
17
19
 
18
- function merge(first: any, second: any): any {
19
- return {
20
- ...first,
21
- ...second,
22
- };
20
+ protected merge(...content: any[]): any {
21
+ return content.reduce((previousValue: any, currentValue: any): any => {
22
+ return {
23
+ ...previousValue,
24
+ ...currentValue,
25
+ };
26
+ });
27
+ }
23
28
  }
@@ -1,5 +1,8 @@
1
+ import ComponentProps from '../BaseProps.ts';
2
+
1
3
  export default interface EditableComponentProps {
2
- content: any;
4
+ key: string;
5
+ content: ComponentProps;
3
6
  additionalContent?: any;
4
7
  index: number;
5
8
  }
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
 
3
- import React, { ReactNode } from 'react';
4
- import Error from './ErrorElement.tsx';
3
+ import React, { ReactNode, Suspense } from 'react';
4
+ import ErrorElement from './ErrorElement.tsx';
5
5
 
6
6
  interface ErrorState {
7
- error: Error;
7
+ error: Error | null;
8
8
  }
9
9
 
10
10
  interface ErrorProps {
@@ -26,8 +26,8 @@ export default class ErrorBoundary extends React.Component<ErrorProps, ErrorStat
26
26
 
27
27
  render() {
28
28
  if (this.state.error) {
29
- return <Error editMode={this.props.isEditMode} throwNotEditMode={this.props.throwNotEditMode} path={this.props.path} msg={this.state.error.message} />;
29
+ return <ErrorElement editMode={this.props.isEditMode} throwNotEditMode={this.props.throwNotEditMode} path={this.props.path} msg={this.state.error.message} />;
30
30
  }
31
- return this.props.children;
31
+ return <Suspense fallback={null}>{this.props.children}</Suspense>;
32
32
  }
33
33
  }
@@ -1,4 +1,29 @@
1
- export default interface Props {
2
- 'mgnl:template': string;
3
- theme: string;
1
+ import { MgnlContent } from '@magnolia/frontend-helpers-base';
2
+
3
+ export interface HrefLangLink {
4
+ language: string;
5
+ href: string;
6
+ }
7
+
8
+ export interface OpenGraph {
9
+ siteName?: string;
10
+ title: string;
11
+ description: string;
12
+ url: string;
13
+ image?: string;
14
+ }
15
+
16
+ export interface MetaProps {
17
+ seoTitle: string;
18
+ description: string;
19
+ keywords: string[];
20
+ robots?: string;
21
+ canonical: string;
22
+ openGraph: OpenGraph;
23
+ hrefLangLinks: HrefLangLink[];
24
+ }
25
+
26
+ export default interface Props extends MgnlContent {
27
+ meta: MetaProps;
28
+ theme?: string;
4
29
  }
@@ -3,14 +3,18 @@ import React, { ReactNode } from 'react';
3
3
  import EditablePageProps from './EditablePageProps.ts';
4
4
  import { IMagnoliaContext } from '@magnolia/frontend-helpers-base';
5
5
  import ErrorBoundary from '../../elements/_error/ErrorBoundary.tsx';
6
+ import { injectable } from 'tsyringe';
6
7
 
7
- export function EditablePage(props: EditablePageProps): ReactNode {
8
- const { content } = props;
9
- const magnoliaContext = RefService.getMagnoliaContextRef<IMagnoliaContext>();
8
+ @injectable()
9
+ export class EditablePage {
10
+ public render(props: EditablePageProps): ReactNode {
11
+ const { content } = props;
12
+ const magnoliaContext: IMagnoliaContext = RefService.getMagnoliaContextRef<IMagnoliaContext>();
10
13
 
11
- return (
12
- <ErrorBoundary isEditMode={magnoliaContext.isMagnoliaEdit} throwNotEditMode={true} path={content!['@path']}>
13
- <MagnoliaEditablePage {...props} />
14
- </ErrorBoundary>
15
- );
14
+ return (
15
+ <ErrorBoundary isEditMode={magnoliaContext.isMagnoliaEdit} throwNotEditMode={true} path={content!['@path']}>
16
+ <MagnoliaEditablePage {...props} />
17
+ </ErrorBoundary>
18
+ );
19
+ }
16
20
  }
@@ -1,10 +1,11 @@
1
- import { IMagnoliaContext, MgnlContent, MgnlTemplateAnnotations } from '@magnolia/frontend-helpers-base';
1
+ import { IMagnoliaContext, MgnlTemplateAnnotations } from '@magnolia/frontend-helpers-base';
2
2
  import { MagnoliaConfig } from '@magnolia/react-editor';
3
3
  import React from 'react';
4
+ import PageProps from '../BaseProps.ts';
4
5
 
5
6
  export default interface EditablePageProps {
6
7
  children?: React.ReactElement | React.ReactElement[] | null;
7
- content: MgnlContent;
8
+ content: PageProps;
8
9
  templateAnnotations: MgnlTemplateAnnotations;
9
10
  config: MagnoliaConfig;
10
11
  magnoliaContext: IMagnoliaContext;
@@ -1,23 +0,0 @@
1
- export interface HrefLangLink {
2
- language: string;
3
- href: string;
4
- }
5
-
6
- export interface OpenGraph {
7
- siteName?: string;
8
- title: string;
9
- description: string;
10
- url: string;
11
- image?: string;
12
- }
13
-
14
- export default interface MetaProps {
15
- seoTitle: string;
16
- description: string;
17
- keywords: string[];
18
- robots?: string;
19
- canonical: string;
20
- openGraph: OpenGraph;
21
- hrefLangLinks: HrefLangLink[];
22
- theme: string;
23
- }