From e393867537b5d782f314e878cbc34429be786eb9 Mon Sep 17 00:00:00 2001 From: Cihan Andac Date: Tue, 13 Feb 2024 10:55:42 +0100 Subject: [PATCH] Changing the Footer's loading to lazy --- .../components/theme/App/App.jsx | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 frontend/src/customizations/components/theme/App/App.jsx diff --git a/frontend/src/customizations/components/theme/App/App.jsx b/frontend/src/customizations/components/theme/App/App.jsx new file mode 100644 index 0000000..335bf09 --- /dev/null +++ b/frontend/src/customizations/components/theme/App/App.jsx @@ -0,0 +1,358 @@ +/** + * App container. + * @module components/theme/App/App + */ + +import React, { Component } from 'react'; +import jwtDecode from 'jwt-decode'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { asyncConnect, Helmet } from '@plone/volto/helpers'; +import { Segment } from 'semantic-ui-react'; +import { renderRoutes } from 'react-router-config'; +import { Slide, ToastContainer, toast } from 'react-toastify'; +import split from 'lodash/split'; +import join from 'lodash/join'; +import trim from 'lodash/trim'; +import cx from 'classnames'; +import config from '@plone/volto/registry'; +import { PluggablesProvider } from '@plone/volto/components/manage/Pluggable'; +import { visitBlocks } from '@plone/volto/helpers/Blocks/Blocks'; +import { injectIntl } from 'react-intl'; + +import Error from '@plone/volto/error'; + +import { + Breadcrumbs, + // Footer, + Header, + Icon, + OutdatedBrowser, + AppExtras, + SkipLinks, +} from '@plone/volto/components'; +import { + BodyClass, + getBaseUrl, + getView, + hasApiExpander, + isCmsUi, +} from '@plone/volto/helpers'; +import { + getBreadcrumbs, + getContent, + getNavigation, + getTypes, + getWorkflow, +} from '@plone/volto/actions'; + +import clearSVG from '@plone/volto/icons/clear.svg'; +import MultilingualRedirector from '@plone/volto/components/theme/MultilingualRedirector/MultilingualRedirector'; +import WorkingCopyToastsFactory from '@plone/volto/components/manage/WorkingCopyToastsFactory/WorkingCopyToastsFactory'; +import LockingToastsFactory from '@plone/volto/components/manage/LockingToastsFactory/LockingToastsFactory'; + +/** + * @export + * @class App + * @extends {Component} + */ +export class App extends Component { + /** + * Property types. + * @property {Object} propTypes Property types. + * @static + */ + static propTypes = { + pathname: PropTypes.string.isRequired, + }; + + state = { + hasError: false, + error: null, + errorInfo: null, + FooterComponent: null, + }; + + constructor(props) { + super(props); + this.mainRef = React.createRef(); + } + + /** + * @method componentWillReceiveProps + * @param {Object} nextProps Next properties + * @returns {undefined} + */ + UNSAFE_componentWillReceiveProps(nextProps) { + if (nextProps.pathname !== this.props.pathname) { + if (this.state.hasError) { + this.setState({ hasError: false }); + } + } + } + + /** + * ComponentDidCatch + * @method ComponentDidCatch + * @param {string} error The error + * @param {string} info The info + * @returns {undefined} + */ + componentDidCatch(error, info) { + this.setState({ hasError: true, error, errorInfo: info }); + config.settings.errorHandlers.forEach((handler) => handler(error)); + } + + dispatchContentClick = (event) => { + if (event.target === event.currentTarget) { + const rect = this.mainRef.current.getBoundingClientRect(); + if (event.clientY > rect.bottom) { + document.dispatchEvent(new Event('voltoClickBelowContent')); + } + } + }; + + componentDidMount() { + this.lazyLoadFooter(); + } + + lazyLoadFooter = () => { + import('@plone/volto/components') + .then((componentsModule) => { + // Destructure the named export 'Footer' from the imported module + const { Footer } = componentsModule; + this.setState({ FooterComponent: Footer }); + }) + .catch((error) => { + // It's a good practice to handle potential errors in dynamic imports + console.error('Failed to load the Footer component', error); + }); + }; + + renderFooter = () => { + const { FooterComponent } = this.state; + // If the FooterComponent has been loaded, render it, otherwise render null or a loader + return FooterComponent ? : null; + }; + + /** + * Render method. + * @method render + * @returns {string} Markup for the component. + */ + render() { + const { views } = config; + const path = getBaseUrl(this.props.pathname); + const action = getView(this.props.pathname); + const isCmsUI = isCmsUi(this.props.pathname); + const ConnectionRefusedView = views.errorViews.ECONNREFUSED; + + const language = + this.props.content?.language?.token ?? this.props.intl?.locale; + + return ( + + {language && ( + + + + )} + + {/* Body class depending on content type */} + {this.props.content && this.props.content['@type'] && ( + + )} + {/* Body class depending on sections */} + + +
+ + + +
+ + {this.props.connectionRefused ? ( + + ) : this.state.hasError ? ( + + ) : ( + renderRoutes(this.props.route.routes, { + staticContext: this.props.staticContext, + }) + )} +
+
+
+ {/*