import { EDBEntity , getStoreItem , isServer , setStoreItem , TCromwellPageCoreProps , TDefaultPageName , TNextDocumentContext , TPageStats , } from '@cromwell/core' ; import { BlockStoreProvider , CContainer , cleanParseContext , getModuleImporter , getParserTransform , getRestApiClient , pageRootContainerId , } from '@cromwell/core-frontend' ; import { AppProps } from 'next/app' ; import { NextRouter } from 'next/router' ; import React , { useRef } from 'react' ; import { ReactNode , useEffect } from 'react' ; import ReactHtmlParser from 'react-html-parser' ; import { CrwDocumentContext , patchDocument } from '../helpers/document' ; import { useForceUpdate } from '../helpers/helpers' ; import { initRenderer } from '../helpers/initRenderer' ; import { usePatchForRedirects } from '../helpers/redirects' ; const DefaultRootComp = ( ( props ) => props . children ) ; type TPageProps = Partial < TCromwellPageCoreProps > & { router ? : NextRouter ; children ? : ReactNode ; } ; type TAppProps = Omit < AppProps < TPageProps > , 'pageProps' > & { pageProps : TPageProps ; } ; export const withCromwellApp = ( App ) => { patchDocument ( ) ; initRenderer ( ) ; return ( props ) => { const pageInstances = useRef ( { } ) ; const Page = props . Component ; const pageProps = props . pageProps ; const { plugins , pageConfig , themeCustomConfig , cmsSettings , themeHeadHtml , themeFooterHtml , documentContext , palette , defaultPages , pageConfigName , resolvedPageRoute , slug } = pageProps ?. cmsProps ?? { } ; const title = pageConfig ?. title ; const description = pageConfig ?. description ; const keywords = pageConfig ?. keywords ?. length && pageConfig . keywords ; const Head = getModuleImporter ( ) ?. modules ?. [ 'next/head' ] ?. default ; const pageId = documentContext ?. fullUrl ?? resolvedPageRoute as string ; const parserTransformHead = getParserTransform ( pageId ) ; const parserTransformBody = getParserTransform ( pageId , { executeScripts : true } ) ; const RootComp = getStoreItem ( 'rendererComponents' ) ?. root ?? DefaultRootComp ; usePatchForRedirects ( ) ; if ( cmsSettings ) setStoreItem ( 'cmsSettings' , Object . assign ( { } , cmsSettings , getStoreItem ( 'cmsSettings' ) ) ) ; if ( plugins ) setStoreItem ( 'plugins' , plugins ) ; if ( pageConfig ) setStoreItem ( 'pageConfig' , pageConfig ) ; if ( defaultPages ) setStoreItem ( 'defaultPages' , defaultPages ) ; if ( themeCustomConfig ) setStoreItem ( 'themeCustomConfig' , themeCustomConfig ) ; if ( palette ) { const theme = getStoreItem ( 'theme' ) ?? { } ; theme . palette = palette ; setStoreItem ( 'theme' , theme ) ; } if ( ! isServer ( ) && documentContext ) { if ( ! documentContext . fullUrl ) documentContext . fullUrl = window . location . href ; if ( ! documentContext . origin ) documentContext . origin = window . location . origin ; if ( documentContext . origin . endsWith ( '/' ) ) documentContext . origin = documentContext . origin . slice ( 0 , documentContext . origin . length - 1 ) ; } setStoreItem ( 'routeInfo' , { origin : documentContext ?. origin , fullUrl : documentContext ?. fullUrl , } ) ; const forceUpdate = useForceUpdate ( ) ; const forceUpdatePage = ( ) => { forceUpdate ( ) ; } ; setStoreItem ( 'forceUpdatePage' , forceUpdatePage ) ; let favicon = cmsSettings ?. favicon ; if ( favicon && favicon !== '' ) { if ( ! favicon . startsWith ( 'http' ) ) { if ( ! favicon . startsWith ( '/' ) ) favicon = '/' + favicon ; if ( documentContext ?. origin ) { favicon = documentContext . origin + favicon ; } } } const getChildAppProps = ( documentContext ) : TAppProps => { return { ... props , router : props . router , pageProps : { ... props . pageProps , cmsProps : { ... ( props . pageProps ?. cmsProps ?? { } ) , documentContext , } } } ; } ; useEffect ( ( ) => { if ( ! isServer ( ) ) { let pageDefaultName ; if ( defaultPages ) { Object . entries ( defaultPages ) . forEach ( entry => { if ( entry [ 1 ] === pageConfigName ) pageDefaultName = entry [ 0 ] as TDefaultPageName ; } ) ; } let entityType = pageDefaultName as any ; if ( pageDefaultName === 'product' ) entityType = EDBEntity . Product ; if ( pageDefaultName === 'category' ) entityType = EDBEntity . ProductCategory ; if ( pageDefaultName === 'post' ) entityType = EDBEntity . Post ; if ( pageDefaultName === 'tag' ) entityType = EDBEntity . Tag ; const apiClient = getRestApiClient ( ) ; const pageStats = { pageRoute : window . location . pathname + window . location . search , pageName : pageConfigName , entityType , slug : Array . isArray ( slug ) ? JSON . stringify ( slug ) : slug , } ; apiClient ?. post ( `v1/cms/view-page` , pageStats , { disableLog : true } ) . catch ( ( ) => null ) ; } } , [ props . router ?. asPath ] ) ; const content = ( < BlockStoreProvider value = { { instances : pageInstances . current } } > < CrwDocumentContext . Consumer > { documentContext => ( < RootComp > < Head > { favicon && ( < link rel = "shortcut icon" type = { favicon . endsWith ( '.png' ) ? 'image/png' : 'image/jpg' } href = { favicon } / > ) } < /Head> < CContainer id = { pageRootContainerId } isConstant = { true } > < App { ... getChildAppProps ( documentContext ) } Component = { Page } / > { cmsSettings ?. footerHtml && ReactHtmlParser ( cmsSettings . footerHtml , { transform : parserTransformBody } ) } { themeFooterHtml && ReactHtmlParser ( themeFooterHtml , { transform : parserTransformBody } ) } { pageConfig ?. footerHtml && ReactHtmlParser ( pageConfig ?. footerHtml , { transform : parserTransformBody } ) } < /CContainer> < Head > { themeHeadHtml && ReactHtmlParser ( themeHeadHtml , { transform : parserTransformHead } ) } { cmsSettings ?. headHtml && ReactHtmlParser ( cmsSettings . headHtml , { transform : parserTransformHead } ) } { title && ( < > < title > { title } < /title> < meta property = "og:title" content = { title } / > < />)} { description && ( < > < meta name = "description" content = { description } / > < meta property = "og:description" content = { description } / > < />)} { keywords && ( < > < meta name = "keywords" content = { keywords . join ( ',' ) } / > < />)} { pageConfig ?. headHtml && ReactHtmlParser ( pageConfig ?. headHtml , { transform : parserTransformHead } ) } < /Head> < /RootComp>)} < /CrwDocumentContext.Consumer> < /BlockStoreProvider>); cleanParseContext ( pageId ) ; return content ; } ; } ;