Skip to content

Commit

Permalink
Refactored ContentTypeSchema.jsx to functional based components
Browse files Browse the repository at this point in the history
  • Loading branch information
BhavishyaSahay authored Jul 28, 2024
1 parent 7137bd4 commit 42b9518
Showing 1 changed file with 116 additions and 214 deletions.
330 changes: 116 additions & 214 deletions packages/volto/src/components/manage/Controlpanels/ContentTypeSchema.jsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
/**
* Content type schema.
* @module components/manage/Controlpanels/ContentTypeSchema
*/
import React, { useEffect, useRef, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { toast } from 'react-toastify';
import { createPortal } from 'react-dom';
import { nth } from 'lodash';
import PropTypes from 'prop-types';
import { Button, Header } from 'semantic-ui-react';

import { getSchema, putSchema } from '@plone/volto/actions';
import { getParentUrl } from '@plone/volto/helpers';
import { nth } from 'lodash';
import { Error, Icon, Toast, Toolbar } from '@plone/volto/components';
import { Form } from '@plone/volto/components/manage/Form';
import clearSVG from '@plone/volto/icons/clear.svg';
import saveSVG from '@plone/volto/icons/save.svg';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import { createPortal } from 'react-dom';
import { connect } from 'react-redux';
import { toast } from 'react-toastify';
import { compose } from 'redux';
import { Button, Header } from 'semantic-ui-react';

const messages = defineMessages({
title: {
Expand Down Expand Up @@ -54,149 +50,60 @@ const messages = defineMessages({
},
});

/**
* ContentTypeSchema class.
* @class ContentTypeSchema
* @extends Component
*/
class ContentTypeSchema extends Component {
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
static propTypes = {
getSchema: PropTypes.func.isRequired,
putSchema: PropTypes.func.isRequired,
pathname: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
};
const ContentTypeSchema = (props) => {
const { getSchema, putSchema, pathname, id, schema, schemaRequest, history } =
props;

/**
* Default properties
* @property {Object} defaultProps Default properties.
* @static
*/
static defaultProps = {};
const [error, setError] = useState(null);
const [isClient, setIsClient] = useState(false);

/**
* Constructor
* @method constructor
* @param {Object} props Component properties
* @constructs WysiwygEditor
*/
constructor(props) {
super(props);
this.state = {
error: null,
schema: null,
content: null,
isClient: false,
};
const formRef = useRef();
const intl = useIntl();

this.onCancel = this.onCancel.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.form = React.createRef();
}
useEffect(() => {
getSchema(id);
setIsClient(true);
}, [getSchema, id]);

/**
* Component did mount
* @method componentDidMount
* @returns {undefined}
*/
componentDidMount() {
this.props.getSchema(this.props.id);
this.setState({ isClient: true });
}

/**
* Component will receive props
* @method componentWillReceiveProps
* @param {Object} nextProps Next properties
* @returns {undefined}
*/
UNSAFE_componentWillReceiveProps(nextProps) {
// Schema error
if (this.props.schemaRequest.loading && nextProps.schemaRequest.error) {
this.setState({
error: nextProps.schemaRequest.error,
});
useEffect(() => {
if (schemaRequest.loading && schemaRequest.error) {
setError(schemaRequest.error);
}

// Schema GET
if (this.props.schemaRequest.loading && nextProps.schemaRequest.loaded) {
let properties = nextProps.schema?.properties || {};
let content = {};
let value, key;
for (key in properties) {
value = properties[key].default;
if (value) {
content[key] = value;
}
}

this.setState({
schema: nextProps.schema,
content: content,
});
}

// Schema updated
if (
this.props.schemaRequest.put.loading &&
nextProps.schemaRequest.put.loaded
) {
// this.props.getSchema(this.props.id);
if (schemaRequest.put.loading && schemaRequest.put.loaded) {
toast.info(
<Toast
info
title={this.props.intl.formatMessage(messages.info)}
content={this.props.intl.formatMessage(messages.changesSaved)}
title={intl.formatMessage(messages.info)}
content={intl.formatMessage(messages.changesSaved)}
/>,
);
}

// Schema update error
if (
this.props.schemaRequest.put.loading &&
nextProps.schemaRequest.put.error
) {
if (schemaRequest.put.loading && schemaRequest.put.error) {
toast.error(
<Toast
error
title={this.props.intl.formatMessage(messages.error)}
title={intl.formatMessage(messages.error)}
content={JSON.stringify(
nextProps.schemaRequest.put.error.response.body ||
nextProps.schemaRequest.put.error.response.text,
schemaRequest.put.error.response.body ||
schemaRequest.put.error.response.text,
)}
/>,
);
}
}
}, [schemaRequest, intl]);

/**
* Submit handler
* @method onSubmit
* @param {object} data Form data.
* @returns {undefined}
*/
onSubmit(data) {
this.props.putSchema(this.props.id, data.schema);
}

/**
* Cancel handler
* @method onCancel
* @returns {undefined}
*/
onCancel() {
let url = getParentUrl(this.props.pathname);
this.props.history.push(getParentUrl(url));
}
const onSubmit = (data) => {
putSchema(id, data.schema);
};

form = React.createRef();
const onCancel = () => {
let url = getParentUrl(pathname);
history.push(getParentUrl(url));
};

makeSchemaList = (schema) => {
const makeSchemaList = (schema) => {
const result = {
title: 'Schema',
type: 'object',
Expand All @@ -223,18 +130,17 @@ class ContentTypeSchema extends Component {
return result;
};

isEditable = (field) =>
const isEditable = (field) =>
!field.behavior || field.behavior.includes('generated');

makeSchemaData = (schema, contentType) => {
const makeSchemaData = (schema, contentType) => {
const fieldsets = schema.fieldsets.map((fieldset) => {
const readOnlyFields = fieldset.fields.filter(
(fieldId) =>
!this.isEditable(schema.properties[fieldId]) &&
fieldId !== 'changeNote',
!isEditable(schema.properties[fieldId]) && fieldId !== 'changeNote',
);
const userCreatedFields = fieldset.fields.filter((fieldId) =>
this.isEditable(schema.properties[fieldId]),
isEditable(schema.properties[fieldId]),
);
const changeNote = fieldset.fields.filter(
(fieldId) => fieldId === 'changeNote',
Expand All @@ -253,88 +159,84 @@ class ContentTypeSchema extends Component {
return { schema: JSON.stringify(result) };
};

/**
* Render method.
* @method render
* @returns {string} Markup for the component.
*/
render() {
// Error
if (this.state.error) {
return <Error error={this.state.error} />;
}
if (error) {
return <Error error={error} />;
}

if (this.state.schema) {
const contentTypeSchema = this.makeSchemaList(this.state.schema);
const schemaData = this.makeSchemaData(this.state.schema, this.props.id);
if (schema) {
const contentTypeSchema = makeSchemaList(schema);
const schemaData = makeSchemaData(schema, id);

return (
<div id="page-controlpanel-schema" className="ui container">
<Header disabled>
{intl.formatMessage(messages.title, {
id: schema?.title || id,
})}
</Header>
<Form
ref={formRef}
schema={contentTypeSchema}
formData={schemaData}
pathname={pathname}
onSubmit={onSubmit}
onCancel={onCancel}
hideActions
/>
{isClient &&
createPortal(
<Toolbar
pathname={pathname}
hideDefaultViewButtons
inner={
<>
<Button
id="toolbar-save"
className="save"
aria-label={intl.formatMessage(messages.save)}
onClick={() => formRef.current.onSubmit()}
disabled={schemaRequest.put.loading}
loading={schemaRequest.put.loading}
>
<Icon
name={saveSVG}
className="circled"
size="30px"
title={intl.formatMessage(messages.save)}
/>
</Button>
<Button
className="cancel"
aria-label={intl.formatMessage(messages.cancel)}
onClick={onCancel}
>
<Icon
name={clearSVG}
className="circled"
size="30px"
title={intl.formatMessage(messages.cancel)}
/>
</Button>
</>
}
/>,
document.getElementById('toolbar'),
)}
</div>
);
}

return (
<div id="page-controlpanel-schema" className="ui container">
<Header disabled>
{this.props.intl.formatMessage(messages.title, {
id: this.props?.schema?.title || this.props.id,
})}
</Header>
<Form
ref={this.form}
schema={contentTypeSchema}
formData={schemaData}
pathname={this.props.pathname}
onSubmit={this.onSubmit}
onCancel={this.onCancel}
hideActions
/>
{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.schemaRequest.put.loading}
loading={this.props.schemaRequest.put.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 />;
};

return <div />;
}
}
ContentTypeSchema.propTypes = {
getSchema: PropTypes.func.isRequired,
putSchema: PropTypes.func.isRequired,
pathname: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
};

export default compose(
injectIntl,
connect(
(state, props) => ({
schema: state.schema.schema,
Expand Down

0 comments on commit 42b9518

Please sign in to comment.