diff --git a/src/customizations/volto/components/theme/View/View.jsx b/src/customizations/volto/components/theme/View/View.jsx deleted file mode 100644 index bb7180db7..000000000 --- a/src/customizations/volto/components/theme/View/View.jsx +++ /dev/null @@ -1,308 +0,0 @@ -/** - * backport https://github.com/plone/volto/pull/4854 - * - * View container. - * @module components/theme/View/View - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { Redirect } from 'react-router-dom'; -import { Portal } from 'react-portal'; -import { injectIntl } from 'react-intl'; -import qs from 'query-string'; - -import { - ContentMetadataTags, - Comments, - Tags, - Toolbar, -} from '@plone/volto/components'; -import { listActions, getContent } from '@plone/volto/actions'; -import { - BodyClass, - getBaseUrl, - flattenToAppURL, - getLayoutFieldname, - hasApiExpander, -} from '@plone/volto/helpers'; - -import config from '@plone/volto/registry'; - -/** - * View container class. - * @class View - * @extends Component - */ -class View extends Component { - /** - * Property types. - * @property {Object} propTypes Property types. - * @static - */ - static propTypes = { - actions: PropTypes.shape({ - object: PropTypes.arrayOf(PropTypes.object), - object_buttons: PropTypes.arrayOf(PropTypes.object), - user: PropTypes.arrayOf(PropTypes.object), - }), - listActions: PropTypes.func.isRequired, - /** - * Action to get the content - */ - getContent: PropTypes.func.isRequired, - /** - * Pathname of the object - */ - pathname: PropTypes.string.isRequired, - location: PropTypes.shape({ - search: PropTypes.string, - pathname: PropTypes.string, - }).isRequired, - /** - * Version id of the object - */ - versionId: PropTypes.string, - /** - * Content of the object - */ - content: PropTypes.shape({ - /** - * Layout of the object - */ - layout: PropTypes.string, - /** - * Allow discussion of the object - */ - allow_discussion: PropTypes.bool, - /** - * Title of the object - */ - title: PropTypes.string, - /** - * Description of the object - */ - description: PropTypes.string, - /** - * Type of the object - */ - '@type': PropTypes.string, - /** - * Subjects of the object - */ - subjects: PropTypes.arrayOf(PropTypes.string), - is_folderish: PropTypes.bool, - }), - error: PropTypes.shape({ - /** - * Error type - */ - status: PropTypes.number, - }), - }; - - /** - * Default properties. - * @property {Object} defaultProps Default properties. - * @static - */ - static defaultProps = { - actions: null, - content: null, - versionId: null, - error: null, - }; - - state = { - hasObjectButtons: null, - isClient: false, - }; - - componentDidMount() { - // Do not trigger the actions action if the expander is present - if (!hasApiExpander('actions', getBaseUrl(this.props.pathname))) { - this.props.listActions(getBaseUrl(this.props.pathname)); - } - this.props.getContent( - getBaseUrl(this.props.pathname), - this.props.versionId, - ); - this.setState({ isClient: true }); - } - - /** - * Component will receive props - * @method componentWillReceiveProps - * @param {Object} nextProps Next properties - * @returns {undefined} - */ - UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.pathname !== this.props.pathname) { - // Do not trigger the actions action if the expander is present - if (!hasApiExpander('actions', getBaseUrl(nextProps.pathname))) { - this.props.listActions(getBaseUrl(nextProps.pathname)); - } - this.props.getContent( - getBaseUrl(nextProps.pathname), - this.props.versionId, - ); - } - - if (nextProps.actions.object_buttons) { - const objectButtons = nextProps.actions.object_buttons; - this.setState({ - hasObjectButtons: !!objectButtons.length, - }); - } - } - - /** - * Default fallback view - * @method getViewDefault - * @returns {string} Markup for component. - */ - getViewDefault = () => config.views.defaultView; - - /** - * Get view by content type - * @method getViewByType - * @returns {string} Markup for component. - */ - getViewByType = () => - config.views.contentTypesViews[this.props.content['@type']] || null; - - /** - * Get view by content layout property - * @method getViewByLayout - * @returns {string} Markup for component. - */ - getViewByLayout = () => - config.views.layoutViews[ - this.props.content[getLayoutFieldname(this.props.content)] - ] || null; - - /** - * Cleans the component displayName (specially for connected components) - * which have the Connect(componentDisplayName) - * @method cleanViewName - * @param {string} dirtyDisplayName The displayName - * @returns {string} Clean displayName (no Connect(...)). - */ - cleanViewName = (dirtyDisplayName) => - dirtyDisplayName - .replace('Connect(', '') - .replace('injectIntl(', '') - .replace(')', '') - .replace('connect(', '') - .toLowerCase(); - - /** - * Render method. - * @method render - * @returns {string} Markup for the component. - */ - render() { - const { views } = config; - const status = __SERVER__ - ? this.props.error?.status - : this.props.error?.code; - // Checking to see if it's a 3XX HTTP status code. error.status only works on the server - if (['301', '302', '307', '308'].includes(status?.toString())) { - const redirectUrl = __SERVER__ - ? this.props.error.response.headers.location - : this.props.error.url; - let redirect = flattenToAppURL(redirectUrl); - // We can hit situations where we end up being redirected to an api route. We don't want that so lets remove ++api++. - redirect = redirect.replace('/++api++', '').replace(/\?.*/, ''); - return ; - } else if (this.props.error && !this.props.connectionRefused) { - let FoundView; - if (this.props.error.status === undefined) { - // For some reason, while development and if CORS is in place and the - // requested resource is 404, it returns undefined as status, then the - // next statement will fail - FoundView = views.errorViews.corsError; - } else { - FoundView = views.errorViews[this.props.error.status.toString()]; - } - if (!FoundView) { - FoundView = views.errorViews['404']; // default to 404 - } - return ( -
- -
- ); - } - if (!this.props.content) { - return ; - } - const RenderedView = - this.getViewByLayout() || this.getViewByType() || this.getViewDefault(); - - return ( -
- - {/* Body class if displayName in component is set */} - - - {config.settings.showTags && - this.props.content.subjects && - this.props.content.subjects.length > 0 && ( - - )} - {/* Add opt-in social sharing if required, disabled by default */} - {/* In the future this might be parameterized from the app config */} - {/* */} - {this.props.content.allow_discussion && ( - - )} - {this.state.isClient && ( - - } /> - - )} -
- ); - } -} - -export default compose( - injectIntl, - connect( - (state, props) => ({ - actions: state.actions.actions, - token: state.userSession.token, - content: state.content.data, - error: state.content.get.error, - apiError: state.apierror.error, - connectionRefused: state.apierror.connectionRefused, - pathname: props.location.pathname, - versionId: - qs.parse(props.location.search) && - qs.parse(props.location.search).version, - }), - { - listActions, - getContent, - }, - ), -)(View);