UNPKG

@plone/volto

Version:
283 lines (266 loc) 7.77 kB
/** * Content Type component. * @module components/manage/Controlpanels/ContentType */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { compose } from 'redux'; import { getParentUrl } from '@plone/volto/helpers/Url/Url'; import { createPortal } from 'react-dom'; import { Button, Header } from 'semantic-ui-react'; import { defineMessages, injectIntl } from 'react-intl'; import { toast } from 'react-toastify'; import last from 'lodash/last'; import nth from 'lodash/nth'; import join from 'lodash/join'; import Error from '@plone/volto/components/theme/Error/Error'; import Icon from '@plone/volto/components/theme/Icon/Icon'; import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar'; import Toast from '@plone/volto/components/manage/Toast/Toast'; import { Form } from '@plone/volto/components/manage/Form'; import { getControlpanel, updateControlpanel, } from '@plone/volto/actions/controlpanels/controlpanels'; import saveSVG from '@plone/volto/icons/save.svg'; import clearSVG from '@plone/volto/icons/clear.svg'; const messages = defineMessages({ title: { id: '{id} Content Type', defaultMessage: '{id} Content Type', }, changesSaved: { id: 'Changes saved.', defaultMessage: 'Changes saved.', }, back: { id: 'Back', defaultMessage: 'Back', }, save: { id: 'Save', defaultMessage: 'Save', }, cancel: { id: 'Cancel', defaultMessage: 'Cancel', }, info: { id: 'Info', defaultMessage: 'Info', }, }); /** * ContentType class. * @class ContentType * @extends Component */ class ContentType extends Component { /** * Property types. * @property {Object} propTypes Property types. * @static */ static propTypes = { updateControlpanel: PropTypes.func.isRequired, getControlpanel: PropTypes.func.isRequired, id: PropTypes.string.isRequired, parent: PropTypes.string.isRequired, cpanelRequest: PropTypes.objectOf(PropTypes.any).isRequired, controlpanel: PropTypes.shape({ '@id': PropTypes.string, data: PropTypes.object, schema: PropTypes.object, title: PropTypes.string, }), pathname: PropTypes.string.isRequired, }; /** * Default properties. * @property {Object} defaultProps Default properties. * @static */ static defaultProps = { controlpanel: null, }; /** * Constructor * @method constructor * @param {Object} props Component properties * @constructs ContentType */ constructor(props) { super(props); this.state = { visual: false, error: null, isClient: false, }; this.onCancel = this.onCancel.bind(this); this.onSubmit = this.onSubmit.bind(this); this.form = React.createRef(); } /** * Component did mount * @method componentDidMount * @returns {undefined} */ componentDidMount() { this.props.getControlpanel(join([this.props.parent, this.props.id], '/')); this.setState({ isClient: true }); } /** * Component will receive props * @method componentWillReceiveProps * @param {Object} nextProps Next properties * @returns {undefined} */ UNSAFE_componentWillReceiveProps(nextProps) { // Control Panel GET if ( this.props.cpanelRequest.get.loading && nextProps.cpanelRequest.get.error ) { this.setState({ error: nextProps.cpanelRequest.get.error, }); } // Control Panel PATCH if ( this.props.cpanelRequest.update.loading && nextProps.cpanelRequest.update.loaded ) { toast.info( <Toast info title={this.props.intl.formatMessage(messages.info)} content={this.props.intl.formatMessage(messages.changesSaved)} />, ); } } /** * Submit handler * @method onSubmit * @param {object} data Form data. * @returns {undefined} */ onSubmit(data) { this.props.updateControlpanel(this.props.controlpanel['@id'], data); } /** * Cancel handler * @method onCancel * @returns {undefined} */ onCancel() { this.props.history.push(getParentUrl(this.props.pathname)); } /** * Render method. * @method render * @returns {string} Markup for the component. */ render() { // Error if (this.state.error) { return <Error error={this.state.error} />; } if (this.props.controlpanel) { let controlpanel = this.props.controlpanel; if (controlpanel?.data?.filter_content_types === false) { controlpanel.data.filter_content_types = { title: 'all', token: 'all' }; } if (controlpanel?.data?.filter_content_types === true) { if ((controlpanel?.data?.allowed_content_types || []).length) { controlpanel.data.filter_content_types = { title: 'some', token: 'some', }; } else { controlpanel.data.filter_content_types = { title: 'none', token: 'none', }; } } return ( <div id="page-controlpanel" className="ui container"> <Header disabled> {this.props.intl.formatMessage(messages.title, { id: controlpanel.title, })} </Header> <Form isEditForm ref={this.form} schema={controlpanel.schema} formData={controlpanel.data} onSubmit={this.onSubmit} onCancel={this.onCancel} pathname={this.props.pathname} visual={this.state.visual} hideActions loading={this.props.cpanelRequest.update.loading} /> {this.state.isClient && createPortal( <Toolbar pathname={this.props.pathname} hideDefaultViewButtons inner={ <> <Button id="toolbar-save" className="save" aria-label={this.props.intl.formatMessage(messages.save)} onClick={() => this.form.current.onSubmit()} disabled={this.props.cpanelRequest.update.loading} loading={this.props.cpanelRequest.update.loading} > <Icon name={saveSVG} className="circled" size="30px" title={this.props.intl.formatMessage(messages.save)} /> </Button> <Button className="cancel" aria-label={this.props.intl.formatMessage( messages.cancel, )} onClick={() => this.onCancel()} > <Icon name={clearSVG} className="circled" size="30px" title={this.props.intl.formatMessage(messages.cancel)} /> </Button> </> } />, document.getElementById('toolbar'), )} </div> ); } return <div />; } } export default compose( injectIntl, connect( (state, props) => ({ controlpanel: state.controlpanels.controlpanel, cpanelRequest: state.controlpanels, pathname: props.location.pathname, id: last(props.location.pathname.split('/')), parent: nth(props.location.pathname.split('/'), -2), }), { getControlpanel, updateControlpanel }, ), )(ContentType);